• SpringSecurity (六) --------- 杂项



    一、其它权限校验方法

    ​我们前面都是使用 @PreAuthorize 注解,然后在在其中使用的是 hasAuthority 方法进行校验。SpringSecurity 还为我们提供了其它方法例如:hasAnyAuthority,hasRole,hasAnyRole等。


    这里我们先不急着去介绍这些方法,我们先去理解 hasAuthority 的原理,然后再去学习其他方法你就更容易理解,而不是死记硬背区别。并且我们也可以选择定义校验方法,实现我们自己的校验逻辑。

    ​hasAuthority 方法实际是执行到了 SecurityExpressionRoot 的 hasAuthority,大家只要断点调试既可知道它内部的校验原理。

    ​它内部其实是调用 authentication 的 getAuthorities 方法获取用户的权限列表。然后判断我们存入的方法参数数据在权限列表中。

    ​hasAnyAuthority 方法可以传入多个权限,只有用户有其中任意一个权限都可以访问对应资源。

    @PreAuthorize("hasAnyAuthority('admin','test','system:dept:list')")
    public String hello(){
        return "hello";
    }
    
    • 1
    • 2
    • 3
    • 4

    hasRole要求有对应的角色才可以访问,但是它内部会把我们传入的参数拼接上 ROLE_ 后再去比较。所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。

    @PreAuthorize("hasRole('system:dept:list')")
    public String hello(){
        return "hello";
    }
    
    • 1
    • 2
    • 3
    • 4

    二、自定义权限校验方法

    我们也可以定义自己的权限校验方法,在@PreAuthorize注解中使用我们的方法。

    @Component("ex")
    public class SGExpressionRoot {
    
        public boolean hasAuthority(String authority){
            //获取当前用户的权限
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            List<String> permissions = loginUser.getPermissions();
            //判断用户权限集合中是否存在authority
            return permissions.contains(authority);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在 SPEL 表达式中使用 @ex 相当于获取容器中 bean 的名字未 ex 的对象。然后再调用这个对象的hasAuthority 方法

     @RequestMapping("/hello")
     @PreAuthorize("@ex.hasAuthority('system:dept:list')")
     public String hello(){
         return "hello";
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、基于配置的权限控制

    我们也可以在配置类中使用使用配置的方式对资源进行权限控制。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录接口 允许匿名访问
                .antMatchers("/user/login").anonymous()
                .antMatchers("/testCors").hasAuthority("system:dept:list222")
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();
    
        //添加过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    
        //配置异常处理器
        http.exceptionHandling()
                //配置认证失败处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);
    
        //允许跨域
        http.cors();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    四、CSRF

    CSRF 是指跨站请求伪造(Cross-site request forgery),是 web 常见的攻击之一。

    https://blog.csdn.net/freeking101/article/details/86537087

    ​SpringSecurity 去防止 CSRF 攻击的方式就是通过 csrf_token。后端会生成一个 csrf_token,前端发起请求的时候需要携带这个 csrf_token,后端会有过滤器进行校验,如果没有携带或者是伪造的就不允许访问。

    ​我们可以发现 CSRF 攻击依靠的是 cookie 中所携带的认证信息。但是在前后端分离的项目中我们的认证信息其实是 token,而 token 并不是存储中 cookie 中,并且需要前端代码去把 token 设置到请求头中才可以,所以 CSRF 攻击也就不用担心了。

    五、认证成功处理器

    ​实际上在 UsernamePasswordAuthenticationFilter 进行登录认证的时候,如果登录成功了是会调用AuthenticationSuccessHandler 的方法进行认证成功后的处理的。AuthenticationSuccessHandler 就是登录成功处理器。

    我们也可以自己去自定义成功处理器进行成功后的相应处理。

    @Component
    public class SGSuccessHandler implements AuthenticationSuccessHandler {
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            System.out.println("认证成功了");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private AuthenticationSuccessHandler successHandler;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin().successHandler(successHandler);
    
            http.authorizeRequests().anyRequest().authenticated();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    六、认证失败处理器

    ​实际上在 UsernamePasswordAuthenticationFilter 进行登录认证的时候,如果认证失败了是会调用AuthenticationFailureHandler 的方法进行认证失败后的处理的。AuthenticationFailureHandler 就是登录失败处理器。

    ​我们也可以自己去自定义失败处理器进行失败后的相应处理。

    @Component
    public class SGFailureHandler implements AuthenticationFailureHandler {
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
            System.out.println("认证失败了");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private AuthenticationSuccessHandler successHandler;
    
        @Autowired
        private AuthenticationFailureHandler failureHandler;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()
    //                配置认证成功处理器
                    .successHandler(successHandler)
    //                配置认证失败处理器
                    .failureHandler(failureHandler);
    
            http.authorizeRequests().anyRequest().authenticated();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    七、登出成功处理器

    @Component
    public class SGLogoutSuccessHandler implements LogoutSuccessHandler {
        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            System.out.println("注销成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private AuthenticationSuccessHandler successHandler;
    
        @Autowired
        private AuthenticationFailureHandler failureHandler;
    
        @Autowired
        private LogoutSuccessHandler logoutSuccessHandler;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin()
    //                配置认证成功处理器
                    .successHandler(successHandler)
    //                配置认证失败处理器
                    .failureHandler(failureHandler);
    
            http.logout()
                    //配置注销成功处理器
                    .logoutSuccessHandler(logoutSuccessHandler);
    
            http.authorizeRequests().anyRequest().authenticated();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    QT-飞机水平仪图标
    基于SSM的健身房管理系统
    测试时大量TIME_WAIT
    Debian 12.5 一键安装 Oracle 19C 单机
    机器学习笔记之配分函数(二)——随机最大似然
    基于协同过滤进行金融产品个性化推荐 代码+数据
    自适应点云配准(RANSAC、ICP)
    Linux C进程间通信(IPC)
    LeetCode每日一题——902. 最大为 N 的数字组合
    Vue3中级指南-如何在vite中使用svg图标
  • 原文地址:https://blog.csdn.net/m0_51111980/article/details/127366171