一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情。
大家好,我是程序员路飞,三年的下水道打杂前端,喜欢研究技术,正在往全栈发展
欢迎小伙伴们加我微信:DZHningmeng,一起讨论,期待与大家共同成长🥂
前言
这是Spring Boot集成Spring Security的第六章,我将会通过这个系列文章,包括完整的项目搭建、编码过程实现(认证和授权),关键点讲解,来帮助大家了解Spring Security在实际项目中的应用
今天这篇内容是捕获全局接口的统一异常
往期系列
Spring Boot集成Spring Security系列一之搭建项目
Spring Boot集成Spring Security系列二之查询用户
Spring Boot集成Spring Security系列三之自定义登录
Spring Boot集成Spring Security系列四之接口鉴权
Spring Boot集成Spring Security系列五之Redis持久化缓存
Spring Boot集成Spring Security系列六之缓存操作异常
功能实现
需求
本篇文章通过捕获全局接口的统一异常(通用和业务性质的),返回给前端展示
- 通用的比如参数的校验,抛出
username is required的信息给前端 - 业务性质的比如
user的status为0,抛出user is locked的信息给前端
编码
编写全局异常处理类
package com.example.springsecurity.common.exception;
import com.example.springsecurity.common.api.IErrorCode;
/**
* 自定义API异常
* Created by Lu Fei on 2022/04/20.
*/
public class ApiException extends RuntimeException {
private String errorCode;
private String errorMessage;
public ApiException(IErrorCode errorCode) {
this.errorCode = errorCode.getCode();
this.errorMessage = errorCode.getMessage();
}
public ApiException(String message) {
super(message);
}
public ApiException(Throwable cause) {
super(cause);
}
public ApiException(String message, Throwable cause) {
super(message, cause);
}
public String getErrorCode() {
return errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
}
package com.example.springsecurity.common.exception;
import com.example.springsecurity.common.api.CommonResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = ApiException.class)
public CommonResult handle(ApiException e) {
if(e.getErrorCode() != null) {
return new CommonResult(e.getErrorCode(), e.getErrorMessage());
}
return CommonResult.failed();
}
}
修改UserServiceImpl
定义接口参数断言工具类
package com.example.springsecurity.common.exception;
import com.example.springsecurity.common.api.IErrorCode;
import org.springframework.util.StringUtils;
public class ApiExceptionAsserts {
public static void hasText(String text, IErrorCode errorCode) {
if(!StringUtils.hasText(text)) {
throw new ApiException(errorCode);
}
}
}
public String login(String username, String password) {
ApiExceptionAsserts.hasText(username, UserResultCode.USERNAME_REQUIRED);
ApiExceptionAsserts.hasText(password, UserResultCode.PASSWORD_REQUIRED);
String token = null;
try {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
System.out.println(userDetails.toString());
if(!passwordEncoder.matches(password, userDetails.getPassword())){
throw new BadCredentialsException("密码不正确");
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
token = jwtTokenUtil.generateToken(userDetails);
} catch (Exception e) {
e.printStackTrace();
LOGGER.warn("登录异常: {}", e.getMessage());
}
return token;
}
验证
启动项目
- 没有
username的情况
- 没有
password的情况
- user status为0的情况
数据库修改admin的status为0
小结
这篇文章我们实现了接口的统一异常处理,结合案例讲解,可以应用到实际的生成中。
🚴♀️ 结束语
通过项目实践,结合具体的步骤,输出相关的文章,给小伙伴一些有些的知识点,希望大家喜欢我的文章,希望认识到更多志同道合的伙伴,如果你也对技术感兴趣,可以加我好友,互相探讨,一起进步
Github: Cheering-baby
公众号: 程序员路飞
vx: DZHningmeng
最后,如果喜欢我的文章,可以给个赞👍或者关注➕都是对我最大的支持