Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 5740|回复: 0

Spring boot 前后台分离项目 怎么处理spring security 抛出的异常

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-19 13:32:23 | 显示全部楼层 |阅读模式

    最近在开发一个项目 前后台分离的 使用 spring boot + spring security + jwt 实现用户登录权限控制等操作。但是 在用户登录的时候,怎么处理spring  security  抛出的异常呢?使用了@RestControllerAdvice 和@ExceptionHandler 不能处理Spring Security抛出的异常,如 UsernameNotFoundException等,我想要友好的给前端返回提示信息  如,用户名不存在之类的。 贴上我的代码:

    JWT 验证类 : 重写了spring security UsernamaPasswordAuthenticationFilter

    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); } } }

    验证用户名 密码:

    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); } }

    全局异常处理

    @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); } }

    登录时输入错误的用户名

    控制台直接打印信息了, 并没有经过ExceptionHandler 处理。

    如上所示,我想在全局异常类中 处理spring security抛出异常, 以便返回友好的提示信息。有什么解决办法么?

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-5 08:10 , Processed in 0.066074 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表