我正在开发一个Spring Boot应用程序,使用Spring Security来检查用户登录是否成功或用户是否有权访问其中的资源。
现在,无论输入的用户名/密码错误还是用户被锁定,它始终返回401未经授权。我想自定义它,说如果凭据错误,它将返回400,如果用户被锁定,它将返回401。
我已经为应用程序定义了自定义过滤器和身份验证入口点。
public class JWTUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
....
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
Optional<UserEntity> userEntity = userService
.findByUserId(request.getParameter("username"));
if (userEntity.isPresent()) {
if (userEntity.get().getStatus().equals("LOCKED")) {
throw new BadCredentialsException("User is locked!"); //I want it to return status 403 here
}
}
String privateKey = userService.findByUserId(request.getParameter("username")).get().getLoginKey();
String username = request.getParameter("username");
String password = CryptoUtil.decrypt(privateKey, request.getParameter("password"));
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
password, Collections.emptyList());
return authenticationManager.authenticate(authenticationToken);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
String username = request.getParameter("username");
try {
// Do some process stuff....
} catch (Exception ex) {
log.error(ex);
}
super.unsuccessfulAuthentication(request, response, failed); // I want to return 400 here
}
}
public class JwtAuthenticationExceptionEntryPoint implements AuthenticationEntryPoint {
@Getter
@Value("${application.version}")
private String version;
@Getter
@Value("${application.name}")
private String applicationName;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
RESTFulStatus status = new RESTFulStatus(RESTFulStatus.STATUS_ERROR, HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
authException.getMessage(), version, applicationName, Instant.now(), request.getRequestURI());
log.error(authException.getMessage());
ObjectMapper mapper = new ObjectMapper();
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(mapper.writeValueAsString(status));
}
}
配置类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationExceptionEntryPoint authenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().cacheControl();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.csrf().disable();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.addFilter(new JWTUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig, userService, accessHistoryService))
.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtConfig)).authorizeRequests();
http.authorizeRequests().antMatchers(HttpMethod.POST, jwtConfig.getUri()).permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/1/**").hasRole(RoleConstant.ROLE_ADMIN)
.antMatchers("/test/**").hasAnyRole(RoleConstant.ROLE_ADMIN)
.antMatchers("/report/**").hasAnyRole(RoleConstant.ROLE_ADMIN, RoleConstant.ROLE_REPORT)
.anyRequest().authenticated();
// If a user try to access a resource without having enough permissions
http.exceptionHandling().accessDeniedPage("/login");
//test in browser
http.httpBasic();
}
}
答案 0 :(得分:1)
扩展UsernamePasswordAuthenticationFilter
时,您可以自定义AuthenticationFailureHandler
,attemptAuthentication()
抛出AuthenticationException
时将调用它。
AuthenticationFailureHandler
看起来像:
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler{
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
RESTFulStatus status = new RESTFulStatus(RESTFulStatus.STATUS_ERROR, HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
authException.getMessage(), version, applicationName, Instant.now(), request.getRequestURI());
log.error(exception.getMessage());
ObjectMapper mapper = new ObjectMapper();
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(mapper.writeValueAsString(status));
}
}
注意:
attemptAuthentication()
会抛出AuthenticationException
如果身份验证失败。 AuthenticationFailureHandler
设置为
JWTUsernameAndPasswordAuthenticationFilter
在配置过程中