我想在BasicAuthenticationFilter身份验证失败时抛出AuthenticationException,并统一处理,返回json。
但ExceptionTranslationFilter不起作用。
在ExceptionTranslationFilter.doFilter()中,它将检查response.isCommitted()并抛出“Unable to handle the Spring Security Exception because the response is already committed”。
所以这是正常的吗?我如何统一处理这些身份验证?
dependencies:spring-security:6.1.5.
SecurityFilterChain:
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(sessionManagement ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilter(new JWTAuthenticationFilter(authenticationConfiguration.getAuthenticationManager(), objectMapper, whitelist))
.addFilterAfter(new DecryptRequestFilter(), JWTAuthenticationFilter.class)
.addFilterBefore(new ExceptionTranslationFilter(unauthorizedEntryPoint), JWTAuthenticationFilter.class)
.build();
}
字符串
JWTAuthenticationFilter中的doFilterInternal()扩展了BasicAuthenticationFilter:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = request.getRequestURI();
AntPathMatcher antPathMatcher = new AntPathMatcher();
if (whitelist.getWhitelist().stream().anyMatch(s -> antPathMatcher.match(s, path))) {
chain.doFilter(request, response);
}
String token = request.getHeader(ConstantKey.HEADER_TOKEN_KEY);
if(StringUtils.isEmpty(token)) {
throw new AuthenticationCredentialsNotFoundException("token not found");
}
String subject = Jwts.parser().setSigningKey(ConstantKey.TOKEN_SIGN_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
if (StringUtils.isEmpty(subject)) {
throw new AuthenticationCredentialsNotFoundException("token is invalid");
}
AuthSubject authSubject;
try {
authSubject = objectMapper.readValue(subject, AuthSubject.class);
}catch (Exception e) {
throw new AuthenticationServiceException("read auth subject error", e);
}
Set<SimpleGrantedAuthority> simpleGrantedAuthorities = authSubject.getRoles().stream()
.map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(authSubject.getUsername(), null, simpleGrantedAuthorities);
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
request.setAttribute(AuthSubject.Fields.username, authSubject.getUsername());
request.setAttribute(AuthSubject.Fields.roles, authSubject.getUserId());
chain.doFilter(request, response);
}
型
UnauthorizedEntryPoint中的begin()实现AuthenticationEntryPoint:
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType(ContentType.APPLICATION_JSON.toString());
response.getWriter().write(objectMapper.writeValueAsString(
GenericRestResponse.builder()
.status(YesOrNo.NO.getCode())
.message(authException.getMessage())
.build()
)
);
}
型
我尝试使用AuthenticationFailureException,但仍然无法捕获AuthenticationException。
1条答案
按热度按时间piok6c0g1#
我使用Spring Authorization Server来实现oauth2认证服务器。
参考youlai-mall项目实现密码认证方法。