返回介绍

12.3 自定义异常配置

发布于 2025-04-26 13:16:48 字数 4007 浏览 0 评论 0 收藏

Spring Security 中默认提供的异常处理器不一定满足我们的需求,如果开发者需要自定义,也是可以的,定义方式如下:

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http.authorizeRequests()
                   .antMatchers("/admin").hasRole("admin")
                   .anyRequest().authenticated()
                   .and()
                   .exceptionHandling()
                   .authenticationEntryPoint((req,resp,e)->{
                      resp.setStatus(HttpStatus.UNAUTHORIZED.value());
                      resp.getWriter().write("please login");
                  })
                  .accessDeniedHandler((req,resp,e)->{
                      resp.setStatus(HttpStatus.FORBIDDEN.value());
                      resp.getWriter().write("forbidden");
                   })
                   .and()
                   .formLogin()
                   .and()
                   .csrf().disable();
       }
    }

首先我们设置了访问/admin 接口必须具备 admin 角色,其他接口只需要认证就可以访问。然后我们对 exceptionHandling 分别配置了 authenticationEntryPoint 和 accessDeniedHandler。回顾上一小节的源码分析,这里配置完成后,defaultEntryPointMappings 和 defaultDeniedHandler Mappings 中的处理器就会失效。

接下来我们启动项目,如果用户未经登录就访问/hello 接口,则结果如图 12-1 所示。

图 12-1 认证失败响应

当用户登录成功后,但是不具备 admin 角色,此时如果访问/admin 接口,则结果如图 12-2 所示。

图 12-2 鉴权失败响应

当然,开发者也可以为不同的接口配置不同的异常处理器,配置方式如下:

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           AntPathRequestMatcher matcher1 = new AntPathRequestMatcher("/qq/**");
           AntPathRequestMatcher matcher2 = new AntPathRequestMatcher("/wx/**");
           http.authorizeRequests()
                   .antMatchers("/wx/**").hasRole("wx")
                   .antMatchers("/qq/**").hasRole("qq")
                   .anyRequest().authenticated()
                   .and()
                   .exceptionHandling()
                   .defaultAuthenticationEntryPointFor((req, resp, e) -> {
                       resp.setContentType("text/html;charset=utf-8");
                       resp.setStatus(HttpStatus.UNAUTHORIZED.value());
                       resp.getWriter().write("请登录,QQ 用户");
                   }, matcher1)
                   .defaultAuthenticationEntryPointFor((req, resp, e) -> {
                       resp.setContentType("text/html;charset=utf-8");
                       resp.setStatus(HttpStatus.UNAUTHORIZED.value());
                       resp.getWriter().write("请登录,WX 用户");
                   }, matcher2)
                   .defaultAccessDeniedHandlerFor((req, resp, e) -> {
                       resp.setContentType("text/html;charset=utf-8");
                       resp.setStatus(HttpStatus.FORBIDDEN.value());
                       resp.getWriter().write("权限不足,QQ 用户");
                   }, matcher1)
                   .defaultAccessDeniedHandlerFor((req, resp, e) -> {
                       resp.setContentType("text/html;charset=utf-8");
                       resp.setStatus(HttpStatus.FORBIDDEN.value());
                       resp.getWriter().write("权限不足,WX 用户");
                   }, matcher2)
                   .and()
                   .formLogin()
                   .and()
                   .csrf().disable();
       }
    }

一开始我们定义了两个路径匹配器 matcher1 和 matcher2,然后配置/wx/**格式的路径需要有 wx 角色才能访问,/qq/**格式的路径则需要有 qq 角色才可以访问。接下来分别调用 defaultAuthenticationEntryPointFor 方法和 defaultAccessDeniedHandlerFor 方法向 defaultEntry PointMappings 和 defaultDeniedHandlerMappings 两个变量中添加异常处理器即可。

配置完成后,启动项目进行测试,不同接口将会给出不同的异常响应,这里不再赘述。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。