Spring Security —— 异常处理

Posted _瞳孔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Security —— 异常处理相关的知识,希望对你有一定的参考价值。

一:异常体系

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

  • AuthenticationException:认证异常
  • AccessDeniedException:授权异常

其中认证所涉及的异常类型比较多,默认有18种,如下:

相比于认证异常,权限异常类就要少了很多,默认提供的权限异常如下:

二:自定义异常配置

在实际开发中,默认异常是无法满足需求的,需要大量的自定义异常类,Spring Security提供了两个方法来配置:

  • authenticationEntryPoint():认证自定义异常
  • accessDeniedHandler():授权自定义异常

至于这两个方法怎么使用,我们可以进入源码看看

首先是authenticationEntryPoint(),可以看到,该方法要求我们传入AuthenticationEntryPoint的对象

	public ExceptionHandlingConfigurer<H> authenticationEntryPoint(
			AuthenticationEntryPoint authenticationEntryPoint) 
		this.authenticationEntryPoint = authenticationEntryPoint;
		return this;
	

进入AuthenticationEntryPoint接口,可以看到只有一个方法,因此在authenticationEntryPoint方法中可以直接传入Lambda表达式,但那样写不美观,配置与实现应该分离,因此我们可以新建一个类去实现这个接口

public interface AuthenticationEntryPoint 
	/**
	 * 处理认证访问相关异常
	 * @param request 导致AuthenticationException的请求
	 * @param response 响应
	 * @param authException 异常信息
	 */
	void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) throws IOException, ServletException;

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint 
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException 
        Map<String, Object> result = new HashMap<>();
        result.put("code", 400);
        result.put("msg", authException.getMessage());
        response.setContentType("application/json;charset=UTF-8");
        String s = new ObjectMapper().writeValueAsString(result);
        response.getWriter().println(s);
    

accessDeniedHandler()方法同理,其源码如下:

	public ExceptionHandlingConfigurer<H> accessDeniedHandler(
			AccessDeniedHandler accessDeniedHandler) 
		this.accessDeniedHandler = accessDeniedHandler;
		return this;
	

进入AccessDeniedHandler接口:

public interface AccessDeniedHandler 
	/**
	 * 处理权限访问相关异常
	 * @param request 导致AccessDeniedException的请求
	 * @param response 响应
	 * @param accessDeniedException 异常信息
	 */
	void handle(HttpServletRequest request, HttpServletResponse response,
			AccessDeniedException accessDeniedException) throws IOException,
			ServletException;

因此我们可以这样实现:

public class CustomAccessDeniedHandler implements AccessDeniedHandler 
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException 
        Map<String, Object> result = new HashMap<>();
        result.put("code", 400);
        result.put("msg", accessDeniedException.getMessage());
        response.setContentType("application/json;charset=UTF-8");
        String s = new ObjectMapper().writeValueAsString(result);
        response.getWriter().println(s);
    

最后再在configure中将自定义处理配置进去:

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests()
                .mvcMatchers("/hello1").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .successHandler(new CustomAuthenticationSuccessHandler())
                .failureHandler(new CustomAuthenticationFailureHandler())
                .and()
                .logout()
                .logoutSuccessHandler(new CustomLogoutSuccessHandler())
                // 异常处理
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint())  // 认证异常
                .accessDeniedHandler(new CustomAccessDeniedHandler())  // 授权异常;
    

如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:瞳孔的个人网站

以上是关于Spring Security —— 异常处理的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常