下面列出了怎么用org.springframework.security.authentication.DisabledException的API类实例代码及写法,或者点击链接到github查看源代码。
private SecurityUser authenticateByUserId(Long userId) {
UserEntity user = userService.findUserById(userId);
if (user == null) {
throw new UsernameNotFoundException("User not found by refresh token");
}
UserCredentialsEntity userCredentials = userService.findUserCredentialsByUserId(user.getId());
if (userCredentials == null) {
throw new UsernameNotFoundException("User credentials not found");
}
if (!userCredentials.isEnabled()) {
throw new DisabledException("User is not active");
}
if (user.getAuthority() == null) {
throw new InsufficientAuthenticationException("User has no authority assigned");
}
UserPrincipal userPrincipal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);
return securityUser;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 为了支持多类型登录,这里username后面拼装上登录类型,如username|type
String[] params = username.split("\\|");
username = params[0];// 真正的用户名
LoginAppUser loginAppUser = userClient.findByUsername(username);
if (loginAppUser == null) {
throw new AuthenticationCredentialsNotFoundException("用户不存在");
} else if (!loginAppUser.isEnabled()) {
throw new DisabledException("用户已作废");
}
if (params.length > 1) {
// 登录类型
CredentialType credentialType = CredentialType.valueOf(params[1]);
if (CredentialType.PHONE == credentialType) {// 短信登录
handlerPhoneSmsLogin(loginAppUser, params);
} else if (CredentialType.WECHAT_OPENID == credentialType) {// 微信登陆
handlerWechatLogin(loginAppUser, params);
}
}
return loginAppUser;
}
/**
* 验证用户输入的验证码
* @param inputVerifyCode
* @return
*/
public boolean validateVerifyCode(String inputVerifyCode){
//获取当前线程绑定的request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 这个VerifyCodeFactory.SESSION_KEY是在servlet中存入session的名字
HttpSession session = request.getSession();
String verifyCode = (String)session.getAttribute(VerifyCodeUtil.SESSION_KEY);
if(null == verifyCode || verifyCode.isEmpty()){
log.warn("验证码过期请重新验证");
throw new DisabledException("验证码过期,请重新验证");
}
// 不分区大小写
verifyCode = verifyCode.toLowerCase();
inputVerifyCode = inputVerifyCode.toLowerCase();
log.info("验证码:{}, 用户输入:{}", verifyCode, inputVerifyCode);
return verifyCode.equals(inputVerifyCode);
}
/**
* 验证用户输入的验证码
* @param inputVerifyCode
* @return
*/
public boolean validateVerifyCode(String inputVerifyCode){
//获取当前线程绑定的request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 这个VerifyCodeFactory.SESSION_KEY是在servlet中存入session的名字
HttpSession session = request.getSession();
String verifyCode = (String)session.getAttribute(VerifyCodeUtil.SESSION_KEY);
if(null == verifyCode || verifyCode.isEmpty()){
log.warn("验证码过期请重新验证");
throw new DisabledException("验证码过期,请重新验证");
}
// 不分区大小写
verifyCode = verifyCode.toLowerCase();
inputVerifyCode = inputVerifyCode.toLowerCase();
log.info("验证码:{}, 用户输入:{}", verifyCode, inputVerifyCode);
return verifyCode.equals(inputVerifyCode);
}
/**
* 验证用户输入的验证码
* @param inputVerifyCode
* @return
*/
public boolean validateVerifyCode(String inputVerifyCode){
//获取当前线程绑定的request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 这个VerifyCodeFactory.SESSION_KEY是在servlet中存入session的名字
HttpSession session = request.getSession();
String verifyCode = (String)session.getAttribute(VerifyCodeUtil.SESSION_KEY);
if(null == verifyCode || verifyCode.isEmpty()){
log.warn("验证码过期请重新验证");
throw new DisabledException("验证码过期,请重新验证");
}
// 不分区大小写
verifyCode = verifyCode.toLowerCase();
inputVerifyCode = inputVerifyCode.toLowerCase();
log.info("验证码:{}, 用户输入:{}", verifyCode, inputVerifyCode);
return verifyCode.equals(inputVerifyCode);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(isProtectedUrl(request)) {
String verifyCode = request.getParameter("verifyCode");
if(!validateVerify(verifyCode)) {
//手动设置异常
request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION",new DisabledException("验证码输入错误"));
// 转发到错误Url
request.getRequestDispatcher("/login/error").forward(request,response);
} else {
filterChain.doFilter(request,response);
}
} else {
filterChain.doFilter(request,response);
}
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 获取用户输入的用户名和密码
String inputName = authentication.getName();
String inputPassword = authentication.getCredentials().toString();
CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();
String verifyCode = details.getVerifyCode();
if (!validateVerify(verifyCode)) {
throw new DisabledException("验证码输入错误");
}
// userDetails为数据库中查询到的用户信息
UserDetails userDetails = customUserDetailsService.loadUserByUsername(inputName);
// 这里直接偷懒手动密码校验了,也可以通过注入 passwordEncode 实现
if (!userDetails.getPassword().equals(inputPassword)) {
throw new BadCredentialsException("密码错误");
}
return new UsernamePasswordAuthenticationToken(inputName, inputPassword, userDetails.getAuthorities());
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(isProtectedUrl(request)) {
String verifyCode = request.getParameter(SecurityConstants.VALIDATE_CODE_PARAMETER);
if(!validateVerify(verifyCode)) {
//手动设置异常
request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION",new DisabledException("验证码输入错误"));
// 转发到错误Url
request.getRequestDispatcher(SecurityConstants.VALIDATE_CODE_ERR_URL).forward(request,response);
} else {
filterChain.doFilter(request,response);
}
} else {
filterChain.doFilter(request,response);
}
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(isProtectedUrl(request)) {
String verifyCode = request.getParameter(SecurityConstants.VALIDATE_CODE_PARAMETER);
if(!validateVerify(verifyCode)) {
//手动设置异常
request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION",new DisabledException("验证码输入错误"));
// 转发到错误Url
request.getRequestDispatcher(SecurityConstants.VALIDATE_CODE_ERR_URL).forward(request,response);
} else {
filterChain.doFilter(request,response);
}
} else {
filterChain.doFilter(request,response);
}
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (isProtectedUrl(request)) {
String verifyCode = request.getParameter("verifyCode");
if (!validateVerify(verifyCode)) {
//手动设置异常
request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", new DisabledException("验证码输入错误"));
// 转发到错误Url
request.getRequestDispatcher("/login/error").forward(request, response);
} else {
filterChain.doFilter(request, response);
}
} else {
filterChain.doFilter(request, response);
}
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (isProtectedUrl(request)) {
String verifyCode = request.getParameter("verifyCode");
if (!validateVerify(verifyCode)) {
//手动设置异常
request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", new DisabledException("验证码输入错误"));
// 转发到错误Url
request.getRequestDispatcher("/login/error").forward(request, response);
} else {
filterChain.doFilter(request, response);
}
} else {
filterChain.doFilter(request, response);
}
}
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpStatus.NOT_FOUND.value());
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
PrintWriter printWriter = httpServletResponse.getWriter();
// 检查 e 是否为验证码错误类
if (e instanceof VerifyCodeFilter.VerifyCodeCheckException) {
printWriter.write(common.objectToJson(new FailureEntity(e.getMessage(), 0)));
} else if (e instanceof BadCredentialsException) {
printWriter.write(common.objectToJson(failureEntity.i18n("user.login_fail_account_or_password_error")));
} else if (e instanceof DisabledException) {
LOGGER.info("e.getMessage={}", e.getMessage());
printWriter.write(common.objectToJson(failureEntity.i18n("user.login_fail_account_or_password_error")));
}
e.printStackTrace();
printWriter.flush();
printWriter.close();
}
private SecurityUser authenticateByUserId(UserId userId) {
User user = userService.findUserById(userId);
if (user == null) {
throw new UsernameNotFoundException("User not found by refresh token");
}
UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getId());
if (userCredentials == null) {
throw new UsernameNotFoundException("User credentials not found");
}
if (!userCredentials.isEnabled()) {
throw new DisabledException("User is not active");
}
if (user.getAuthority() == null) throw new InsufficientAuthenticationException("User has no authority assigned");
UserPrincipal userPrincipal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);
return securityUser;
}
private SecurityUser authenticateByUserId(UserId userId) {
User user = userService.findUserById(userId);
if (user == null) {
throw new UsernameNotFoundException("User not found by refresh token");
}
UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getId());
if (userCredentials == null) {
throw new UsernameNotFoundException("User credentials not found");
}
if (!userCredentials.isEnabled()) {
throw new DisabledException("User is not active");
}
if (user.getAuthority() == null)
throw new InsufficientAuthenticationException("User has no authority assigned");
UserPrincipal userPrincipal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);
return securityUser;
}
@Override
protected void onInitialize() {
super.onInitialize();
// Vérification des retours d'auth pac4J
HttpServletRequest request = ((ServletWebRequest) RequestCycle.get().getRequest()).getContainerRequest();
Exception exception = (Exception) request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
if (exception != null) {
if (exception instanceof DisabledException) {
getSession().error(getString("home.identification.classic.error.userDisabled"));
} else if (exception instanceof AuthenticationServiceException) {
LOGGER.error("Authentication failed", exception);
getSession().error(getString("home.identification.error.badCredentials") + exception.getMessage());
} else {
LOGGER.error("An unknown error occurred during the authentication process", exception);
getSession().error(getString("home.identification.error.unknown"));
}
request.getSession().removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
}
@Override
protected void onInitialize() {
super.onInitialize();
// Vérification des retours d'auth pac4J
HttpServletRequest request = ((ServletWebRequest) RequestCycle.get().getRequest()).getContainerRequest();
Exception exception = (Exception) request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
if (exception != null) {
if (exception instanceof DisabledException) {
getSession().error(getString("home.identification.classic.error.userDisabled"));
} else if (exception instanceof AuthenticationServiceException) {
LOGGER.error("Authentication failed", exception);
getSession().error(getString("home.identification.error.badCredentials") + exception.getMessage());
} else {
LOGGER.error("An unknown error occurred during the authentication process", exception);
getSession().error(getString("home.identification.error.unknown"));
}
request.getSession().removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
}
private Authentication authenticate(String username, String password) {
try {
// 该方法会去调用userDetailsService.loadUserByUsername()去验证用户名和密码,
// 如果正确,则存储该用户名密码到security 的 context中
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException | BadCredentialsException e) {
throw new CustomException(ResultJson.failure(ResultCode.LOGIN_ERROR, e.getMessage()));
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 后续考虑集成spring socail,支持多种类型登录
LoginAppUser loginAppUser = userClient.findByUsername(username); //方式1 feign调用 对外feign resttemplate
// LoginAppUser loginAppUser = userLoginGrpc.findByUsername(username); //方式2 gprc调用 对内grpc dubbo
if (loginAppUser == null) {
throw new AuthenticationCredentialsNotFoundException("用户不存在");
} else if (!loginAppUser.isEnabled()) {
throw new DisabledException("用户已作废");
}
return loginAppUser;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//用户输入的用户名
String username = authentication.getName();
//用户输入的密码
String password = authentication.getCredentials().toString();
//通过CustomWebAuthenticationDetails获取用户输入的验证码信息
CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();
String verifyCode = details.getVerifyCode();
if(null == verifyCode || verifyCode.isEmpty()){
log.warn("未输入验证码");
throw new NullPointerException("请输入验证码");
}
//校验验证码
if(!validateVerifyCode(verifyCode)){
log.warn("验证码输入错误");
throw new DisabledException("验证码输入错误");
}
//通过自定义的CustomUserDetailsService,以用户输入的用户名查询用户信息
CustomUserDetails userDetails = (CustomUserDetails) userDetailsService.loadUserByUsername(username);
//校验用户密码
if(!userDetails.getPassword().equals(password)){
log.warn("密码错误");
throw new BadCredentialsException("密码错误");
}
Object principalToReturn = userDetails;
//将用户信息塞到SecurityContext中,方便获取当前用户信息
return this.createSuccessAuthentication(principalToReturn, authentication, userDetails);
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//用户输入的用户名
String username = authentication.getName();
//用户输入的密码
String password = authentication.getCredentials().toString();
//通过CustomWebAuthenticationDetails获取用户输入的验证码信息
CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();
String verifyCode = details.getVerifyCode();
if(null == verifyCode || verifyCode.isEmpty()){
log.warn("未输入验证码");
throw new NullPointerException("请输入验证码");
}
//校验验证码
if(!validateVerifyCode(verifyCode)){
log.warn("验证码输入错误");
throw new DisabledException("验证码输入错误");
}
//通过自定义的CustomUserDetailsService,以用户输入的用户名查询用户信息
CustomUserDetails userDetails = (CustomUserDetails) userDetailsService.loadUserByUsername(username);
//校验用户密码
if(!userDetails.getPassword().equals(password)){
log.warn("密码错误");
throw new BadCredentialsException("密码错误");
}
Object principalToReturn = userDetails;
//将用户信息塞到SecurityContext中,方便获取当前用户信息
return this.createSuccessAuthentication(principalToReturn, authentication, userDetails);
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//用户输入的用户名
String username = authentication.getName();
//用户输入的密码
String password = authentication.getCredentials().toString();
//通过CustomWebAuthenticationDetails获取用户输入的验证码信息
CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails();
String verifyCode = details.getVerifyCode();
if(null == verifyCode || verifyCode.isEmpty()){
log.warn("未输入验证码");
throw new NullPointerException("请输入验证码");
}
//校验验证码
if(!validateVerifyCode(verifyCode)){
log.warn("验证码输入错误");
throw new DisabledException("验证码输入错误");
}
//通过自定义的CustomUserDetailsService,以用户输入的用户名查询用户信息
CustomUserDetails userDetails = (CustomUserDetails) userDetailsService.loadUserByUsername(username);
//校验用户密码
String pwEncode = MD5Util.encryptMd5Password2(password).toLowerCase();
if(!userDetails.getPassword().toLowerCase().equals(pwEncode)){
log.warn("密码错误");
throw new BadCredentialsException("密码错误");
}
Object principalToReturn = userDetails;
//将用户信息塞到SecurityContext中,方便获取当前用户信息
return this.createSuccessAuthentication(principalToReturn, authentication, userDetails);
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ApiResponse handlerException(Exception e) {
if (e instanceof NoHandlerFoundException) {
log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e).getHttpMethod());
return ApiResponse.ofStatus(Status.REQUEST_NOT_FOUND);
} else if (e instanceof HttpRequestMethodNotSupportedException) {
log.error("【全局异常拦截】HttpRequestMethodNotSupportedException: 当前请求方式 {}, 支持请求方式 {}", ((HttpRequestMethodNotSupportedException) e).getMethod(), JSONUtil.toJsonStr(((HttpRequestMethodNotSupportedException) e).getSupportedHttpMethods()));
return ApiResponse.ofStatus(Status.HTTP_BAD_METHOD);
} else if (e instanceof MethodArgumentNotValidException) {
log.error("【全局异常拦截】MethodArgumentNotValidException", e);
return ApiResponse.of(Status.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult()
.getAllErrors()
.get(0)
.getDefaultMessage(), null);
} else if (e instanceof ConstraintViolationException) {
log.error("【全局异常拦截】ConstraintViolationException", e);
return ApiResponse.of(Status.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations())
.getMessage(), null);
} else if (e instanceof MethodArgumentTypeMismatchException) {
log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage());
return ApiResponse.ofStatus(Status.PARAM_NOT_MATCH);
} else if (e instanceof HttpMessageNotReadableException) {
log.error("【全局异常拦截】HttpMessageNotReadableException: 错误信息 {}", ((HttpMessageNotReadableException) e).getMessage());
return ApiResponse.ofStatus(Status.PARAM_NOT_NULL);
} else if (e instanceof BadCredentialsException) {
log.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
return ApiResponse.ofStatus(Status.USERNAME_PASSWORD_ERROR);
} else if (e instanceof DisabledException) {
log.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
return ApiResponse.ofStatus(Status.USER_DISABLED);
} else if (e instanceof BaseException) {
log.error("【全局异常拦截】DataManagerException: 状态码 {}, 异常信息 {}", ((BaseException) e).getCode(), e.getMessage());
return ApiResponse.ofException((BaseException) e);
}
log.error("【全局异常拦截】: 异常信息 {} ", e.getMessage());
return ApiResponse.ofStatus(Status.ERROR);
}
@Override
public void check(UserDetails user) {
if (!user.isAccountNonLocked()) {
log.debug("User account is locked");
throw new LockedException(AbstractUserDetailsAuthenticationProvider.this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"));
} else if (!user.isEnabled()) {
log.debug("User account is disabled");
throw new DisabledException(AbstractUserDetailsAuthenticationProvider.this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"));
} else if (!user.isAccountNonExpired()) {
log.debug("User account is expired");
throw new AccountExpiredException(AbstractUserDetailsAuthenticationProvider.this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"));
}
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ApiResponse handlerException(Exception e) {
if (e instanceof NoHandlerFoundException) {
log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e).getHttpMethod());
return ApiResponse.ofStatus(Status.REQUEST_NOT_FOUND);
} else if (e instanceof HttpRequestMethodNotSupportedException) {
log.error("【全局异常拦截】HttpRequestMethodNotSupportedException: 当前请求方式 {}, 支持请求方式 {}", ((HttpRequestMethodNotSupportedException) e).getMethod(), JSONUtil.toJsonStr(((HttpRequestMethodNotSupportedException) e).getSupportedHttpMethods()));
return ApiResponse.ofStatus(Status.HTTP_BAD_METHOD);
} else if (e instanceof MethodArgumentNotValidException) {
log.error("【全局异常拦截】MethodArgumentNotValidException", e);
return ApiResponse.of(Status.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult()
.getAllErrors()
.get(0)
.getDefaultMessage(), null);
} else if (e instanceof ConstraintViolationException) {
log.error("【全局异常拦截】ConstraintViolationException", e);
return ApiResponse.of(Status.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations())
.getMessage(), null);
} else if (e instanceof MethodArgumentTypeMismatchException) {
log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage());
return ApiResponse.ofStatus(Status.PARAM_NOT_MATCH);
} else if (e instanceof HttpMessageNotReadableException) {
log.error("【全局异常拦截】HttpMessageNotReadableException: 错误信息 {}", ((HttpMessageNotReadableException) e).getMessage());
return ApiResponse.ofStatus(Status.PARAM_NOT_NULL);
} else if (e instanceof BadCredentialsException) {
log.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
return ApiResponse.ofStatus(Status.USERNAME_PASSWORD_ERROR);
} else if (e instanceof DisabledException) {
log.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
return ApiResponse.ofStatus(Status.USER_DISABLED);
} else if (e instanceof BaseException) {
log.error("【全局异常拦截】DataManagerException: 状态码 {}, 异常信息 {}", ((BaseException) e).getCode(), e.getMessage());
return ApiResponse.ofException((BaseException) e);
}
log.error("【全局异常拦截】: 异常信息 {} ", e.getMessage());
return ApiResponse.ofStatus(Status.ERROR);
}
public void addErrors(Model model, HttpServletRequest request) {
String message = "Username or Password is incorrect!";
Object exception = request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
Object rawUsername = request.getSession().getAttribute(UsernameAuthenticationFailureHandler.USERNAME);
// If exception is null, show default message
if (exception != null && rawUsername instanceof String) {
String coolDownPeriod = getBlockDuration() + " " + LoginAttemptService.TIME_UNIT;
String username = (String) rawUsername;
if (exception instanceof LockedException || isBlocked(username)) {
message = "User blocked for <strong>" + coolDownPeriod + "</strong> since last wrong login attempt";
} else if (exception instanceof BadCredentialsException) {
String tries = String.format("%d out of %d tries left!", triesLeft(username), getMaxRetries());
String coolDown = "User will be blocked for " + coolDownPeriod + " after all tries are exhausted";
String errorMessage = extractMessage((BadCredentialsException) exception, message);
// If the error is about OTP, tell frontend that OTP is required
if (errorMessage.toLowerCase().contains("otp")) {
model.addAttribute("otp_required", true);
}
message = errorMessage + "<br><strong>" + tries + "</strong> " + coolDown;
} else if (exception instanceof DisabledException) {
message = "User is disabled from site";
}
}
model.addAttribute("login_error", message);
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ApiResponse handlerException(Exception e) {
if (e instanceof NoHandlerFoundException) {
log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e).getHttpMethod());
return ApiResponse.ofStatus(Status.REQUEST_NOT_FOUND);
} else if (e instanceof HttpRequestMethodNotSupportedException) {
log.error("【全局异常拦截】HttpRequestMethodNotSupportedException: 当前请求方式 {}, 支持请求方式 {}", ((HttpRequestMethodNotSupportedException) e).getMethod(), JSONUtil.toJsonStr(((HttpRequestMethodNotSupportedException) e).getSupportedHttpMethods()));
return ApiResponse.ofStatus(Status.HTTP_BAD_METHOD);
} else if (e instanceof MethodArgumentNotValidException) {
log.error("【全局异常拦截】MethodArgumentNotValidException", e);
return ApiResponse.of(Status.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult()
.getAllErrors()
.get(0)
.getDefaultMessage(), null);
} else if (e instanceof ConstraintViolationException) {
log.error("【全局异常拦截】ConstraintViolationException", e);
return ApiResponse.of(Status.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations())
.getMessage(), null);
} else if (e instanceof MethodArgumentTypeMismatchException) {
log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage());
return ApiResponse.ofStatus(Status.PARAM_NOT_MATCH);
} else if (e instanceof HttpMessageNotReadableException) {
log.error("【全局异常拦截】HttpMessageNotReadableException: 错误信息 {}", ((HttpMessageNotReadableException) e).getMessage());
return ApiResponse.ofStatus(Status.PARAM_NOT_NULL);
} else if (e instanceof BadCredentialsException) {
log.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
return ApiResponse.ofStatus(Status.USERNAME_PASSWORD_ERROR);
} else if (e instanceof DisabledException) {
log.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
return ApiResponse.ofStatus(Status.USER_DISABLED);
} else if (e instanceof BaseException) {
log.error("【全局异常拦截】DataManagerException: 状态码 {}, 异常信息 {}", ((BaseException) e).getCode(), e.getMessage());
return ApiResponse.ofException((BaseException) e);
}
log.error("【全局异常拦截】: 异常信息 {} ", e.getMessage());
return ApiResponse.ofStatus(Status.ERROR);
}
private Authentication authenticateByUsernameAndPassword(UserPrincipal userPrincipal, String username,
String password) {
User user = userService.findUserByEmail(username);
if (user == null) {
throw new UsernameNotFoundException("User not found: " + username);
}
UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getId());
if (userCredentials == null) {
throw new UsernameNotFoundException("User credentials not found");
}
if (!userCredentials.isEnabled()) {
throw new DisabledException("User is not active");
}
if (!encoder.matches(password, userCredentials.getPassword())) {
throw new BadCredentialsException("Authentication Failed. Username or Password not valid.");
}
if (user.getAuthority() == null)
throw new InsufficientAuthenticationException("User has no authority assigned");
SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);
return new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities());
}
@DataProvider
public static List<List<Throwable>> unauthorized401ExceptionsDataProvider() {
return Stream.<Throwable>of(
new BadCredentialsException("foo"),
new InsufficientAuthenticationException("foo"),
new AuthenticationCredentialsNotFoundException("foo"),
new LockedException("foo"),
new DisabledException("foo"),
new CredentialsExpiredException("foo"),
new AccountExpiredException("foo"),
new UsernameNotFoundException("foo"),
new RemoteAuthenticationException("foo")
).map(Collections::singletonList)
.collect(Collectors.toList());
}
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
ExceptionMappingAuthenticationFailureHandler failureHandler = new ExceptionMappingAuthenticationFailureHandler();
Map<String, String> failureUrlMap = new HashMap<>();
failureUrlMap.put(BadCredentialsException.class.getName(), LoginAuthenticationFailureHandler.PASS_ERROR_URL);
failureUrlMap.put(CaptchaException.class.getName(), LoginAuthenticationFailureHandler.CODE_ERROR_URL);
failureUrlMap.put(AccountExpiredException.class.getName(), LoginAuthenticationFailureHandler.EXPIRED_URL);
failureUrlMap.put(LockedException.class.getName(), LoginAuthenticationFailureHandler.LOCKED_URL);
failureUrlMap.put(DisabledException.class.getName(), LoginAuthenticationFailureHandler.DISABLED_URL);
failureHandler.setExceptionMappings(failureUrlMap);
return failureHandler;
}
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
RequestDispatcher dispatcher = request.getRequestDispatcher(loginUrl);
if (exception instanceof UsernameNotFoundException) {
request.setAttribute("error", "用户名不存在!");
} else if (exception instanceof DisabledException) {
request.setAttribute("error", "用户已被禁用!");
} else if (exception instanceof BadCredentialsException) {
request.setAttribute("error", "用户名或密码错误!");
} else {
request.setAttribute("error", "登陆失败!");
}
dispatcher.forward(request, response);
}