Spring boot 前后台分离项目 怎么处理spring security 抛出的异常
最近在开发一个项目 前后台分离的 使用 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抛出异常, 以便返回友好的提示信息。有什么解决办法么?
Spring boot 前后台分离项目 怎么处理spring security 抛出的异常的更多相关文章
- Spring boot 多模块项目 + Swagger 让你的API可视化
Spring boot 多模块项目 + Swagger 让你的API可视化 前言 手写 Api 文档的几个痛点: 文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时. 接口返回结果不 ...
- 【建议收藏】缺少 Vue3 和 Spring Boot 的实战项目经验?我这儿有啊!
缺少 Vue3 和 Spring Boot 的实战项目经验?缺少学习项目和练手项目?我这儿有啊! 从 2019 年到 2021 年,空闲时间里陆陆续续做了一些开源项目,推荐给大家啊!记得点赞和收藏噢! ...
- 从零一起学Spring Boot之LayIM项目长成记(五)websocket
前言 距离上一篇已经比较久的时间了,项目也是开了个头.并且,由于网上的关于Spring Boot的websocket讲解也比较多.于是我采用了另外的一个通讯框架 t-io 来实现LayIM中的通讯功能 ...
- 从零一起学Spring Boot之LayIM项目长成记(四) Spring Boot JPA 深入了解
前言 本篇内容主要是一些关于JPA的常用的一些用法等.内容也是很多是看其他博客学来的,顺道在本系列博客里抽出一篇作为总结.下面让我们来看看吧. 不过我更推荐大家读本篇:https://lufficc. ...
- 从零一起学Spring Boot之LayIM项目长成记(三) 数据库的简单设计和JPA的简单使用。
前言 今天是第三篇了,上一篇简单模拟了数据,实现了LayIM页面的数据加载.那么今天呢就要用数据库的数据了.闲言少叙,书归正传,让我们开始吧. 数据库 之前有好多小伙伴问我数据库是怎么设计的.我个人用 ...
- Spring Boot 2.0系列文章(五):Spring Boot 2.0 项目源码结构预览
关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/04/15/springboot2_code/ 项目结构 结构分析: Spring-boot-pr ...
- 使用Spring Boot开发Web项目(二)之添加HTTPS支持
上篇博客使用Spring Boot开发Web项目我们简单介绍了使用如何使用Spring Boot创建一个使用了Thymeleaf模板引擎的Web项目,当然这还远远不够.今天我们再来看看如何给我们的We ...
- 使用Spring Boot开发Web项目
前面两篇博客中我们简单介绍了Spring Boot项目的创建.并且也带小伙伴们来DIY了一个Spring Boot自动配置功能,那么这些东西说到底最终还是要回归到Web上才能体现出它的更大的价值,so ...
- spring boot+mybatis+quartz项目的搭建完整版
1. 利用spring boot提供的工具(http://start.spring.io/)自动生成一个标准的spring boot项目架构 2. 因为这里我们是搭建spring boot+mybat ...
随机推荐
- 关于逆元&&lucas定理
lucas是求组合数C(m,n)%p,有一个公式:C(m,n) = C(m/p,n/p)*C(m%p,n%p). (a*b)%c==a%c*b%c,但是(a/b)%c!=a%c/b%c,所以我们要算b ...
- PCB Genesis加邮票孔(弧形连接位宽度校正)实现算法
采用弧形作为加接位,当两边距离较远时,会造成连接位变窄,由于之前算法是基于连接位间距做为半径画弧, 必然存在这个缺陷,这边做少许的改进解决此问题. 现将几个种增加孤形连接位的图形对比如下: 一.两边外 ...
- bzoj 2152 聪聪可可(点分治模板)
2152: 聪聪可可 Time Limit: 3 Sec Memory Limit: 259 MBSubmit: 3194 Solved: 1647[Submit][Status][Discuss ...
- python 46 css组合选择器 及优先级 、属性选择器
一:css组合选择器 特性:每个选择器位可以为任意基本选择器或选择器组合 选择器分为以下几类: 群组选择器,子代(后代)选择器,相邻(兄弟)选择器,交集选择器,多类名选择器 1.群组选择器: d ...
- SqlMap常用参数(一)
sqlmap可谓是利用sql注入的神器了,sqlmap的参数很多,接下介绍几种常见的参数. 一.注入access数据库常用的参数 sqlmap.py -u "url" //判断参 ...
- 【WPF】使用 XAML 的 Trigger 系统实现三态按钮
利用 WPF 的 Trigger 系统,也可以很简单的只使用xmal实现三态按钮.在Window或UserControl的资源中声明按钮的style并加入触发功能.使用的时候直接在button里复写s ...
- CDN 内容分发网络
第一步,HTML的文件引用:HTML的文件头(也有文件中,文件尾)那边常有其他文件引用,比如CSS以及JS的引用. 就以bootstrap常用的引用来举个栗子你常见的引用可能会是这样的: <he ...
- ESB报文自动生成工具
为了提高日常工作效率,自己在闲暇时间写了一款工具,功能界面如下图所示: 从ESB文档中复制报文字段.字段类型.报文字段注释,选择生成文件路径并输入文件名: 输入完毕后点击生成按钮,自动生成Contex ...
- jQueryAjax模拟按键消抖(可设置抖动延迟时间)
在硬件中,按键等都会有抖动现象,如何消除抖动,不重复触发事件呢,这就要用到消抖机制了. 这是我用jQuery模拟硬件消抖原理,额,可能是吧...又不对的地方,希望有高手指点指点. <!DOCTY ...
- CMMI评估流程
原文链接:http://www.cmmcn.com/new/cmmi-105.html 当前位置:首页 >> CMMI知识库 >> CMMI相关 >> CMMI评估 ...