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 ...
随机推荐
- (Go)06. Printf格式化输出、Scanf格式化输入详解
Print.Println .Printf .Sprintf .Fprintf都是fmt 包中的公共方法,在需要打印信息时需要用到这些函数,那么这些函数有什么区别呢? Print: 输出到控制台(不接 ...
- PCB MongoDB数据库 备份与还原
一. MongoDB数据库 备份与还原工具介绍: 数据备份工具 mongodump.exe 数据还原工具 mongorestore.exe 二. MongoDB数据库备份 mongodump - ...
- bzoj2822[AHOI2012]树屋阶梯(卡特兰数)
2822: [AHOI2012]树屋阶梯 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 879 Solved: 513[Submit][Status] ...
- mybatis的二级缓存
在mybatis主配置文件里configuration标签里添加 <settings> <setting name="cacheEnabled" value=&q ...
- SpringCloud(二) 服务注册与发现Eureka
1.eureka是干什么的? 上篇说了,微服务之间需要互相之间通信,那么通信就需要各种网络信息,我们可以通过使用硬编码的方式来进行通信,但是这种方式显然不合适,不可能说一个微服务的地址发生变动,那么整 ...
- 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree
一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log.有一天脑洞大开,想到也许Treap也能从底向上Split.仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现 ...
- java热部署
最近使用java做项目,研究了一下热部署,能够提高工作效率. 需要准备的工具: 1.安装文件http://update.zeroturnaround.com/update-site/ 2.破解 下载破 ...
- MVC微信浏览器图片上传(img转Base64)
因公司业务需要,需要做一个微信公众号里的图片上传功能,主要用到的技术就是 img转base64 上到服务器 话不多说, 贴代码 先看前端显示出来的东西 OK 图片不重要,看代码 <!--微信图片 ...
- CSS元素水平垂直居中的方法
1. 元素水平居中 1.1 设置父元素的属性 text-align: center; 说明:此属性只针对父元素的子元素为内联元素时有效,比如:img,input,select,button等(行内 ...
- JavaScript 浏览器事件解读
1. 事件基本概念 事件是指在文档或者浏览器中发生的一些特定交互瞬间,比如打开某一个网页,浏览器加载完成后会触发 load 事件,当鼠标悬浮于某一个元素上时会触发 hover 事件,当鼠标点击某一个元 ...