spring security 中的异常

一、简介

Spring Security 中异常主要分为两大类:

1、AuthenticationException: 认证异常

2、AccessDeniedException:  授权异常

  • AuthenticationEntryPoint 该类用来统一处理  AuthenticationException 异常

  • AccessDeniedHandler 该类用来统一处理  AccessDeniedException 异常

我们只要实现并配置这两个异常处理类即可实现对 Spring Security 认证授权相关的异常进行统一的自定义处理。

二、AuthenticationException 认证异常

异常介绍:

org.springframework.security.authentication.AccountStatusException  账号相关异常,抽象类,下面有三个实现类

        org.springframework.security.authentication.AccountExpiredException   账号过期异常

        org.springframework.security.authentication.CredentialsExpiredException 凭证过期(密码过期)

        org.springframework.security.authentication.DisabledException  账号禁用异常

        org.springframework.security.authentication.LockedException    账号已锁定异常

        

        

    

2.1 认证异常常用处理

    @Bean
    public LoginFilter loginVerifyImgFilter() throws Exception {
        LoginFilter filter = new LoginFilter();
        filter.setUsernameParameter("loginId");
        filter.setPasswordParameter("pwd");
        filter.setFilterProcessesUrl("/login.do");
        // 成功的响应
        filter.setAuthenticationSuccessHandler((req,resp,auth) -> {
            Map<String,Object> resMap = new HashMap<>();
            resMap.put("code","0000");
            resMap.put("msg","登录成功!");
            resMap.put("data",auth);
            WebRespUtils.writeJson(resp,resMap);
        });
        //登录失败的处理
        filter.setAuthenticationFailureHandler((req,resp,ex) -> {
            Map<String,Object> resMap = new HashMap<>();
            String errMsg = "登录失败";
            resMap.put("code","5001");

            if (ex instanceof LockedException) {
                errMsg = "账户被锁定,请联系管理员!";
            } else if (ex instanceof CredentialsExpiredException) {
                errMsg = "密码过期,请联系管理员!";
            } else if (ex instanceof AccountExpiredException) {
                errMsg = "账户过期,请联系管理员!";
            } else if (ex instanceof DisabledException) {
                errMsg = "账户被禁用,请联系管理员!";
            } else if (ex instanceof BadCredentialsException) {
                errMsg = "用户名或者密码输入错误,请重新输入!";
            }

            resMap.put("msg",errMsg);
            WebRespUtils.writeJson(resp,resMap);
        });

        // 指定自己的authenticationmanager
        filter.setAuthenticationManager(authenticationManagerBean());

        return filter;
    }

三、AccessDeniedException 授权异常

   授权异常 AccessDeniedException,授权异常的实现类比较少,因为授权失败的可能原因比较少,主要是在用户在访问受保护资源时被拒绝而抛出的异常

3.1 401 未授权状态

    HTTP 401 错误 - 未授权(Unauthorized) 一般来说该错误消息表明您首先需要登录(输入有效的用户名和密码)。如果你刚刚输入这些信息,立刻就看到一个 401 错误,就意味着,无论出于何种原因您的用户名和密码其中之一或两者都无效(输入有误,用户名暂时停用,账户被锁定,凭证失效等) 。总之就是认证失败了。其实正好对应我们上面的 AuthenticationException 。

3.2 403 被拒绝状态

    HTTP 403 错误 - 被禁止(Forbidden) 出现该错误表明您在访问受限资源时没有得到许可。服务器理解了本次请求但是拒绝执行该任务,该请求不该重发给服务器。并且服务器想让客户端知道为什么没有权限访问特定的资源,服务器应该在返回的信息中描述拒绝的理由。一般实践中我们会比较模糊的表明原因。该错误对应了我们上面的 AccessDeniedException 。

四、代码处理异常

  自定义认证异常处理类和授权异常处理类:


/*
* 自定义认证异常处理
*/
@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, 
     AuthenticationException authException) throws IOException, ServletException {
            Map<String,Object> resMap = new HashMap<>();
            String errMsg = authException.getMessage();
            resMap.put("code","5001");
            resMap.put("msg",errMsg);
            WebRespUtils.writeJson(response,resMap);
    }
}



/*
* 自定义授权异常处理
*/
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setStatus(403);
            Map<String,Object> resMap = new HashMap<>();
            String errMsg = authException.getMessage();
             resMap.put("code","403");
             resMap.put("msg",errMsg);
            WebRespUtils.writeJson(response,resMap);
    }
}

4.2  SecurityConfig 中进行配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ...
                ...
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(myAuthenticationEntryPoint)
                .accessDeniedHandler(myAccessDeniedHandler)
                .and()
                ...
                ...
    }
}

Spring Security 是一个基于 Spring 的安全框架,其支持多种认证方式、授权方式以及自定义安全过滤器等。在使用 Spring Security 进行开发时,自定义异常处理是非常重要的一部分。下面是 Spring Security 自定义异常处理的步骤: 1. 实现 AuthenticationEntryPoint 接口,该接口用于处理未认证用户的请求。通过实现该接口,可以自定义未认证用户的返回结果,例如返回自定义的 JSON 格式数据或者跳转到自定义的登录页面。 2. 实现 AccessDeniedHandler 接口,该接口用于处理已认证用户但没有权限访问资源的请求。同样可以通过实现该接口,自定义返回结果。 实现以上两个接口之后,需要在 Spring Security 配置进行配置,将自定义实现的类添加到配置即可生效。下面是一个示例配置: ``` @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyAuthenticationEntryPoint myAuthenticationEntryPoint; @Autowired private MyAccessDeniedHandler myAccessDeniedHandler; @Override protected void configure(HttpSecurity http) throws Exception { http.exceptionHandling() .authenticationEntryPoint(myAuthenticationEntryPoint) .accessDeniedHandler(myAccessDeniedHandler) .and() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasAnyRole("USER", "ADMIN") .anyRequest().authenticated() .and() .formLogin().loginPage("/login").permitAll() .and() .logout().permitAll(); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空寻流年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值