Spring boot 先後臺分離項目 怎麼處理spring security 拋出的異常

最近在開發一個項目 先後臺分離的 使用 spring boot + spring security + jwt 實現用戶登陸權限控制等操做。可是 在用戶登陸的時候,怎麼處理spring  security  拋出的異常呢?使用了@RestControllerAdvice 和@ExceptionHandler 不能處理Spring Security拋出的異常,如 UsernameNotFoundException等,我想要友好的給前端返回提示信息  如,用戶名不存在之類的。 貼上個人代碼:前端

JWT 驗證類 : 重寫了spring security UsernamaPasswordAuthenticationFilterjava

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; private RedisServiceImpl redisService; private AppConfig appConfig; public JWTAuthenticationFilter(AuthenticationManager authenticationManager, RedisServiceImpl redisService, AppConfig appConfig) { this.authenticationManager = authenticationManager; this.redisService = redisService; this.appConfig = appConfig; } /** * @param req * @param res * @return * @throws AuthenticationException * @// TODO: 2018/4/12 接受並解析用戶憑證 */ @Override public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException { try { AuthEntity creds = new ObjectMapper() .readValue(req.getInputStream(), AuthEntity.class); //驗證碼校驗 if (appConfig.getCaptchaEnabled()) { //若是開啓了驗證碼登陸校驗功能 if (StringUtils.isBlank(creds.getCaptcha())) { logger.error("驗證碼爲空"); throw new WelendException(StatusCode.CAPTCHA_EMPTY); } if (!redisService.exists(appConfig.getCaptchaKey())) { logger.error("驗證碼已失效"); throw new WelendException(StatusCode.CAPTCHA_OVERDUE); } String captcha = (String) redisService.get(appConfig.getCaptchaKey()); if (!creds.getCaptcha().equals(captcha)) { logger.error("驗證碼不正確"); throw new WelendException(StatusCode.CAPTCHA_ERROR); } } return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword(), new ArrayList<>()) ); } catch (IOException e) { logger.error("Client's variables can't be parsed by com.fasterxml.jackson.core.JsonParse"); throw new WelendException(StatusCode.SERVER_ERROR); } } }

驗證用戶名 密碼:redis

public class CustomAuthenticationProvider implements AuthenticationProvider { private UserDetailsServiceImpl userDetailsService; private BCryptPasswordEncoder bCryptPasswordEncoder; public CustomAuthenticationProvider(UserDetailsServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) { this.userDetailsService = userDetailsService; this.bCryptPasswordEncoder = bCryptPasswordEncoder; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 獲取認證的用戶名 & 密碼 String name = authentication.getName(); String password = authentication.getCredentials().toString(); // 認證邏輯 JWTUserDetails userDetails = userDetailsService.loadUserByUsername(name); if (null != userDetails) { Boolean verifyPwd = bCryptPasswordEncoder.matches(password,userDetails.getLoginPwd()); if (verifyPwd) { // 生成令牌 這裏令牌裏面存入了:userDetails,password,authorities(權限列表) Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities()); return auth; } else { throw new BadCredentialsException("username or password wrong!"); } } else { throw new UsernameNotFoundException("can not find this account"); } } /** * 是否能夠提供輸入類型的認證服務 * @param authentication * @return */ @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } }

全局異常處理spring

@RestControllerAdvice
public class GlobalExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(getClass()); /** * @param request * @param exception * @return * @throws Exception * @// TODO: 2018/4/25 參數未經過驗證異常 */ @ExceptionHandler(value = MethodArgumentNotValidException.class) public Object MethodArgumentNotValidHandler(HttpServletRequest request, MethodArgumentNotValidException exception) throws Exception { //按需從新封裝須要返回的錯誤信息 //List<StatusCode> invalidArguments = new ArrayList<>(); //解析原錯誤信息,封裝後返回,此處返回非法的字段名稱,原始值,錯誤信息 ResultObject resultMsg = ResultObject.dataMsg(exception.getBindingResult().getFieldError().getDefaultMessage(), StatusCode.VARIABLE_ERROR); return resultMsg; } /** * @param request * @param exception * @return * @throws Exception * @// TODO: 2018/4/25 沒法解析參數異常 */ @ExceptionHandler(value = HttpMessageNotReadableException.class) public Object HttpMessageNotReadableHandler(HttpServletRequest request, HttpMessageNotReadableException exception) throws Exception { logger.info(exception.getMessage()); ResultObject resultMsg = ResultObject.dataMsg("參數沒法正常解析", StatusCode.VARIABLE_ERROR); return resultMsg; } /** * @param exception * @return * @throws Exception * @// TODO: 2018/4/25 處理token 過時異常 */ @ExceptionHandler(value = ExpiredJwtException.class) public Object ExpiredJwtExceptionHandler(ExpiredJwtException exception) throws Exception { logger.info(exception.getMessage()); ResultObject resultMsg = ResultObject.dataMsg("登陸已過時!", StatusCode.FORBIDDEN); return resultMsg; } /** * @param request * @param exception * @return * @throws Exception * @// TODO: 2018/4/25 方法訪問權限不足異常 */ @ExceptionHandler(value = AccessDeniedException.class) public Object AccessDeniedExceptionHandler(AccessDeniedException exception) throws Exception { logger.info(exception.getMessage()); ResultObject resultMsg = ResultObject.dataMsg("權限不足!", StatusCode.FORBIDDEN); return resultMsg; } @ExceptionHandler(value = NoHandlerFoundException.class) public Object NoHandlerFoundExceptionHandler(NoHandlerFoundException exception) throws Exception { logger.info(exception.getMessage()); return ResultObject.dataMsg("連接不存在", StatusCode.NOT_FOUND); } /** * 處理自定義異常 */ @ExceptionHandler(value = WelendException.class) public Object WelendExceptionHandler(WelendException e) { ResultObject r = new ResultObject(); r.setStatus(String.valueOf(e.getCode())); r.setMessage(e.getMessage()); return r; } @ExceptionHandler(value = AuthenticationException.class) public Object AuthenticationExceptionHandler(AuthenticationException e) { return ResultObject.dataMsg(e.getLocalizedMessage(),StatusCode.FORBIDDEN); } @ExceptionHandler(value = DuplicateKeyException.class) public Object DuplicateKeyExceptionHandler(DuplicateKeyException e) throws Exception { logger.error(e.getMessage(), e); return ResultObject.codeMsg(StatusCode.EXISTED); } @ExceptionHandler(value = BadCredentialsException.class) public Object BadCredentialsExceptionHandler(BadCredentialsException e) throws Exception { logger.error(e.getMessage(), e); return ResultObject.codeMsg(StatusCode.AUTH_ERROR); } @ExceptionHandler(value = Exception.class) public Object ExceptionHandler(Exception e) throws Exception { logger.error(e.getMessage(), e); return ResultObject.codeMsg(StatusCode.FAILED); } }

登陸時輸入錯誤的用戶名app

控制檯直接打印信息了, 並無通過ExceptionHandler 處理。less

如上所示,我想在全局異常類中 處理spring security拋出異常, 以便返回友好的提示信息。有什麼解決辦法麼?ide

相關文章
相關標籤/搜索