在Spring 框架系列中,Spring Security是个功能强大且高度可定制的身份验证和访问控制框架。它主要专注于为Java应用程序提供身份验证和授权的框架。

官方文档中文版地址

注:当前使用的security框架版本为5.6.1版本,属于旧版的security,security框架从6.x开始配置方式就发生了改变,不在继承WebSecurityConfigurerAdapter抽象类而是使用配置Bean对象的方式进行配置管理,并且书写方式上也开始使用lambda表达式的方式进行配置。

核心功能:

身份验证(Authentication):用于证明你自己是你自己,是用来确认你的身份。

授权(Authorization):用于证明你能做什么,是用来确认你的权限。

框架引入

  1. maven 坐标依赖:传送门

  2. 基础配置:

    环境搭建:新建一个WEB项目,新建springmvc的一个初始化类和两个配置类,再配置spring security的初始化类和配置类,通过springmvc的初始化类在目测的root配置类的位置将security的配置类加载进来。

    创建Controller包,新建一个测试类,在MVC的配置类中将此包加入扫描目录,同时将MVC的Servlet配置类中添加@EnableWebMvc注解,启用注解控制。

  3. **简单配置后效果:**当为项目配置了Spring Security框架后,再去访问项目中的web接口不会直接返回结果,而是先跳转到spring security默认的登录界面,经过登录验证后才可以访问原本接口资源。

  4. spring security 默认配置:

    1. 默认用户名:user
    2. 默认密码:随机生成,在项目启动日志中可以看到
    3. 可以在application.properties文件中指定自己需要的用户名,密码,角色
  5. 自定义进阶配置:

    1. **引入配置:**可以通过配置@EnableWebSecurity注解并继承WebSecurityConfigurerAdapter类来实现,其中注解的作用非常关键,引入了两个核心配置类WebSecurityConfiguration,AuthenticationConfiguration。 配置类所继承的类是使用的适配器模式去实现,

      优点是:可以选择性的覆盖想要修改的部分配置,对于其他的配置部分则无影响。

    2. **常见配置:**在继承了WebSecurityConfigurerAdapter的配置类中,有几个常用的重写的方法

      1. configure(AuthenticationManagerBuilder auth):用于进行身份认证相关的配置。

        • 可以设置用户信息的认证方式,有基于内存、数据库、LDAP等。

        • 可以设置密码的编码器

        • 在基于内存的验证时,添加临时用户,此时密码的编码器是必须的

          // 设置密码编码器
              private BCryptPasswordEncoder encoder =  new BCryptPasswordEncoder();
              @Override
              protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                  auth.inMemoryAuthentication().passwordEncoder(encoder)
                          .withUser("user")
                          .password(encoder.encode("123456"))
                          .roles("user");
              }
          
        • 在基于本地数据库的验证时应注意,Mybatis的加载应放在MVC的root根配置类中引入,并且返回自定义的用户类时,名称、密码和角色都需要有。

          // UserService ,自定义的登录实现类
          public class UserService implements UserDetailsService {
              @Resource
              private UserMapper userMapper;
              
              @Override
              public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                  String password = userMapper.getUser(username);
                  if(password==null){
                      throw new RuntimeException("登录失败,用户名或密码错误!");
                  }else {
                      return User.withUsername(username)
                              .password(password)
                              .roles("user")
                              .build();
                  }
              }
          }
          
          // SecurityConfig ,Security 的配置类
          public class SecurityConfig extends WebSecurityConfigurerAdapter {
              // 设置密码加密器
              private BCryptPasswordEncoder encoder =  new BCryptPasswordEncoder();
              @Resource
              private UserService userService;
          
              @Override
              protected void configure(AuthenticationManagerBuilder auth) throws Exception {
                  auth.userDetailsService(userService)  // 写入自定义的类
                          .passwordEncoder(encoder);
              }
          }
          
      2. configure(HttpSecurity http):用于配置url的权限控制。

        • **特点:**以http 作为根开始配置,每一个 and()对应了一个模块的配置(等同于 xml 配置中的结束标签),并且 and() 返回了 HttpSecurity 本身,于是可以连续进行配置。(链式编程调用)

        • **使用方法:**调用HttpSecurity.authorizeRequests() 方法后,开始配置 URL 的权限控制。authorizeRequests() 作用:配置路径拦截,表明路径访问所对应的权限,角色,认证信息。

        • **注意事项:**在使用spring security4.0版本以上时,默认会打开CSRF保护,此时发出的所有post,put,delete,patch请求,在不添加csrfToken时,都会被拒绝,并返回403页面,需注意此点。

        • 常见方法:

          - antMatchers() 方法,匹配指定url路径
          - anyRequest() 方法,匹配剩余的url请求
          - permitAll() 方法,所有用户可访问。
          - authenticated() 方法,登录用户可访问。
          - denyAll() 方法,所有用户不可访问。
          - anonymous() 方法,无需登录,即匿名用户可访问。
          - rememberMe() 方法,开启记住我功能,通过 remember me 登录的用户可访问。
          - fullyAuthenticated() 方法,非 remember me 登录的用户可访问。
          - hasIpAddress(String ipaddressExpression) 方法,来自指定 IP 表达式的用户可访问。
          - hasRole(String role) 方法, 拥有指定角色的用户可访问。
          - hasAnyRole(String… roles) 方法,拥有指定任一角色的用户可访问。
          - hasAuthority(String authority) 方法,拥有指定权限(authority)的用户可访问。
          - hasAuthority(String… authorities) 方法,拥有指定任一权限(authority)的用户可访问。
          
        • 使用注解进行配置:

          • 启用注解配置:在mvc或者root的相应配置类的根配置类设置注解@EnableGlobalMethodSecurity(securedEnabled=true),就可以启用权限的注解配置,只要是由spring管理的bean都可以使用此方法设置权限,在需要设置权限的方法上设置注解即可实现和重写方法一样的效果。
          • 常见注解有:
            • @PreAuthorize:先确定权限,再执行方法。
            • @PostAuthorize先执行方法,再确定权限。
            • @PreFilter:对于方法的参数值进行过滤,只有与表达式相符合的值能通过过滤,
            • @PostFilter:对于方法的返回值进行过滤,只有与表达式相符合能通过过滤。 按照权限来控制: 通过在认证时设定某些权限来设置用户是否可以访问某些页面 hasAuthority(String authority) hasAnyAuthority(String… authorities)
        • url配置实例:

          @Override
              protected void configure(HttpSecurity http) throws Exception {
                  http.authorizeRequests()
                          .antMatchers("/static/**").permitAll() // 允许静态请求通过
                          .anyRequest().hasAnyRole("user")
                          .and()
                          .formLogin()
                          .loginPage("/login")   // 设置登录页面
                          .loginProcessingUrl("/doLogin")   // 设置登录请求接口
                          .defaultSuccessUrl("/index",true) // 设置登录成功后跳转的页面
                          .failureForwardUrl("/fail")  // 设置登录失败后返回的信息
                          .permitAll()
                          .and()
                          .csrf(AbstractHttpConfigurer::disable); // 关闭CSRF防护
              }
          
  6. 授权配置:

    对于授权来说有两种形式:

    按照角色来控制,是在configure(HttpSecurity http)方法中,设置关于角色的匹配规则,至于角色权限的设置,需要在身份认证的方法中自行设置相应的角色规则。角色在方法中的的指定方式: hasRole(String role) 允许单一角色访问 hasAnyRole(String… roles) 允许多个角色访问

记住我功能