自定义SpringSecurity异常格式

今天发现spring的异常格式没有跟着mvc的错误格式走,场景是用户权限的时候。查了一下原来是springsecurity定义了一组filter作用在了mvc上层,因此需要处理一下错误格式。

处理前错误返回信息如下:

由于使用了多语言,因此错误格式也要跟着多语言走,稍微绕了点弯。配置定义如下:

@Configuration
@AutoConfigureBefore({com.xkcoding.justauth.autoconfigure.JustAuthAutoConfiguration.class})
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

	private RedissonClient redissonClient;

	private SecurityExceptionHandler securityExceptionHandler;

	public SecurityConfigurer(RedissonClient redissonClient, MessageSource messageSource, LocaleResolver localeResolver) {
		this.redissonClient = redissonClient;
		this.securityExceptionHandler = new SecurityExceptionHandler(messageSource, localeResolver);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
				.antMatchers("/"+GlobalEx.ADMIN_URI_PERFIX+"/**").authenticated()
				.antMatchers("/"+GlobalEx.API_URI_PERFIX+"/**").authenticated()
			.and()
				.addFilterAfter(new JwtHeadFilter(redissonClient), UsernamePasswordAuthenticationFilter.class)
				.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
			.and()
				.exceptionHandling().authenticationEntryPoint(securityExceptionHandler).accessDeniedHandler(securityExceptionHandler)
			.and()
				.csrf().disable();

	}
}

主要是
 

.and()
    .exceptionHandling().authenticationEntryPoint(securityExceptionHandler).accessDeniedHandler(securityExceptionHandler)

这一段,定义了权限解析失败以及没有权限时的错误异常

需要对应的interface处理,看了下两个的格式比较接近,逻辑代码也接近,索性一个类处理了这两种解析:

package org.ccframe.commons.auth;

import com.alibaba.fastjson.JSON;
import lombok.extern.log4j.Log4j2;
import org.ccframe.subsys.core.dto.Result;
import org.springframework.context.MessageSource;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;

@Log4j2
public class SecurityExceptionHandler implements AccessDeniedHandler, AuthenticationEntryPoint{

    private final Object[] EMPTY_ARGS = new Object[0];

    private final LocaleResolver localeResolver;

    private final MessageSource messageSource;

    public SecurityExceptionHandler(MessageSource messageSource, LocaleResolver localeResolver){
        this.messageSource = messageSource;
        this.localeResolver = localeResolver;
    }

    private void inner(HttpServletRequest request, HttpServletResponse response, RuntimeException exception, String msgKey) throws IOException {
        Locale currentLocale = localeResolver.resolveLocale(request);
        String message = "";
        message = messageSource.getMessage(msgKey, EMPTY_ARGS, currentLocale); // 未登陆/无权限
        log.error(message, exception);
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setHeader("Content-Type","application/json;charset=utf-8");
        PrintWriter writer = response.getWriter() ;

        writer.write(JSON.toJSONString(Result.error(HttpServletResponse.SC_FORBIDDEN, message, exception.getClass().getName())));
        writer.flush();
        writer.close();
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        inner(request, response, authException, "errors.auth.noAuth");
    }

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        inner(request, response, accessDeniedException, "errors.auth.dataNotPermitted");
    }

}

对应多语言:


运行了一下,发现正常了

已经成为我需要的错误返回格式了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值