Spring Security笔记

383 阅读2分钟

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。

1.核心功能

(1)认证

(2)验证

1.直接引用框架

1.加入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.4.4</version>
        </dependency>
                <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.4.4</version>
        </dependency>

2.创建启动类

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3.创建Controller,接收请求

@RestController
@RequestMapping("/hello")
public class HelloSecurityController {
    @RequestMapping("/world")
    public String sayHello(){
        return "Hello Spring Security";
    }
}

4.在application配置文件中配置用户名密码

spring.security.user.name=
spring.security.user.password=123456

浏览器发起请求,需要进行登录验证才能进入页面

2.使用基于内存的用户信息

使用:WebSecurityConfigurerAdapter控制安全管理的内容 通过继承WebSecurityConfigurerAdapter,重写configure方法来实现

There is no PasswordEncoder mapped for the id "null"

springsecurity要求密码必须加密

//当前类是一个配置类
@Configuration
//表示启用SpringSecurity的功能
@EnableWebSecurity
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    //在方法中配置用户信息,作为登录的数据

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder pe = passwordEncoder();
        auth.inMemoryAuthentication()
                .withUser("yuan")
                .password(pe.encode("123456")).roles();

    }
    //创建密码的加密类
    //把方法返回值的对象放入spring容器中
    @Bean
    public PasswordEncoder passwordEncoder(){
        //创建加密算法实现类
        return new BCryptPasswordEncoder();
    }
}

3.基于角色Role的身份认证

同一个用户可以有不同的角色

1.设置用户的角色

2.在类的上面加入启用方法级别的注解

3.在处理器方法的上面加入角色的信息

//当前类是一个配置类
@Configuration
//表示启用SpringSecurity的功能
@EnableWebSecurity
//启用方法级别的认证
//prePostEnabled = true 表示可以使用@PreAuthorize @PostAuthorize
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    //在方法中配置用户信息,作为登录的数据
    //定义两个角色,normal,admin
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder pe = passwordEncoder();
        auth.inMemoryAuthentication()
                .withUser("yuan")
                .password(pe.encode("123456")).roles("admin","normal");

    }
    //创建密码的加密类
    @Bean
    public PasswordEncoder passwordEncoder(){
        //创建实现类
        return new BCryptPasswordEncoder();
    }
}
//normal admin都可以访问的方法
    @RequestMapping("/helloUser")
    @PreAuthorize(value = "hasAnyRole('admin','normal')")
    public String helloCommomUser(){
        return "Hello 拥有normal admin角色的用户";
    }
    //admin可以访问的方法
    @RequestMapping("/helloAdmin")
    @PreAuthorize(value = "hasAnyRole('admin')")
    public String helloAdmin(){
        return "hello admin";
    }

4.基于JDBC的用户认证

从数据库中获取用户的身份信息

1.对象用户信息的表示类是UserDetails,User类 是UserDetails接口的实现类

User 类:是 UserDetails 接口的实现类, 构造方法有三个参数: username,password, authorities

需要向 spring security 提供 User 对象, 这个对象的数据来自数据库 的查询

2.实现UserDetailsService接口,重写UserDetails loadUserByUsername方法,在方法中获取数据库的用户信息

@Component("MyUserDetailService")
public class MyUserDetailService implements UserDetailsService {
    @Autowired
    private UserInfoDao dao;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo=null;
        if(username!=null){
            userInfo=dao.findByUsername(username);

            if(userInfo!=null){
                List<GrantedAuthority> list=new ArrayList<>();
                GrantedAuthority authority=new SimpleGrantedAuthority("Role_"+userInfo.getRole());
                list.add(authority);
                //创建user对象
                User user=new User(userInfo.getUsername(),userInfo.getPassword(),list);
            }

        }

        return null;
    }
}