Version: Next

认识SpringSecurity

Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!

记住几个类:

  • WebSecurityConfigurerAdapter:自定义Security策略
  • AuthenticationManagerBuilder:自定义认证策略 源码用到适配器模式建造者模式
  • @EnableWebSecurity:开启WebSecurity模式

Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。

“认证”(Authentication)

身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。

身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。

“授权” (Authorization)

授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。

这个概念是通用的,而不是只在Spring Security 中存在。

认证和授权

授权

  • 引入SpringSecurity依赖

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

    可以看到SpringSecurity依赖AOP


  • 编写SpringSecurity配置类SecurityConfig,继承WebSecurityConfigurerAdapter

    • 添加@EnableWebSecurity注解
    • 重写configure(HttpSecurity http)
    • 模拟需求:
      • 首页所有人可以访问
      • 功能页具有对应权限的人才能访问
    //AOP 开闭原则
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    //认证请求.授权请求.允许所有人.授权请求.具有身份
    http.authorizeRequests()
    .antMatchers("/").permitAll()
    .antMatchers("/level1/**").hasRole("vip1")
    .antMatchers("/level2/**").hasRole("vip2")
    .antMatchers("/level3/**").hasRole("vip3");
    }
    }

    再次访问网站,会发现可以访问首页,但功能页403 请求拒绝,权限不足

    添加代码,让没有权限的人被跳转到登录页面

    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    //认证请求.授权请求.允许所有人.授权请求.具有身份
    http.authorizeRequests()
    .antMatchers("/").permitAll()
    .antMatchers("/level1/**").hasRole("vip1")
    .antMatchers("/level2/**").hasRole("vip2")
    .antMatchers("/level3/**").hasRole("vip3");
    //没权限就跳转到登录页面
    http.formLogin();
    }
    }
    问题

    为什么formLogin方法能让我们直接跳到login.html?

    查看源码,它会自动去/login路由


认证

重写configure(AuthenticationManagerBuilder auth)

  • 按照.withUser().password().roles()的顺序写
  • 多个用户之间用.and()连接
  • .roles()支持可变长度参数
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("Alice").password("123456").roles("vip2","vip3")
.and()
.withUser("root").password("root").roles("vip1","vip2","vip3");
}

测试,报错,说密码未加密

There is no PasswordEncoder mapped for the id "null"

添加密码加密,有各种XxxPasswordEncoding可供使用

//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("Alice")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("vip2", "vip3")
.and()
.withUser("root")
.password(new BCryptPasswordEncoder().encode("root"))
.roles("vip1", "vip2", "vip3");
}