Spring Security系列文章目录
关于Spring Security
Spring Security详解(1)
Spring Security详解(2)
Spring Security关于异常的处理
文章目录
前言
前面三期已经介绍完了Spring Security的详细开发流程,这期主要解决Spring Security异常的处理。
提示:以下是本篇文章正文内容,部分代码可供参考
一、处理异常
在登录时,可能出现:
- 用户名错误:
BadCredentialsException
- 密码错误:
BadCredentialsException
- 账号被禁用:
DisabledException
在访问时,可能出现:
- 无此权限:
AccessDeniedException
以上异常都可以由统一处理异常的机制进行处理,关于统一处理异常的机制,参考专栏系列文章之MVC设计思想。则先在ServiceCode
中添加对应的业务状态码:
public interface ServiceCode {
Integer OK = 20000; //成功
Integer ERR_BAD_REQUEST = 40000; //请求参数格式错误
Integer ERR_UNAUTHORIZED = 40100; //未授权登录
Integer ERR_UNAUTHORIZED_DISABLE = 40101; //未授权登录
Integer ERR_FORBIDDEN = 40300; //无权限访问
Integer ERR_NOT_FOUND = 40400; //相关资源或数据不存在
Integer ERR_CONFLICT = 40900; //数据冲突,例如尝试添加不允许重复的数据
Integer ERR_INSERT = 50001; //插入数据时的错误
Integer ERR_DELETE = 50002; //删除数据时的错误
Integer ERR_UPDATE = 50003; //修改数据时的错误
Integer ERR_INTERNAL_SERVER_ERROR = 50000; //服务器内部错误,通常是未确定的异常类型
Integer ERR_JWT_PARSE = 60000; //解析jwt失败:格式错误,或签名错误
Integer ERR_JWT_EXPIRED = 60001; //解析jwt失败:过期
}
然后,在统一处理异常的类中,添加对相关异常的处理:
@ExceptionHandler
public JsonResult<Void> handleBadCredentialsException(BadCredentialsException e) {
String message = "登录失败,用户名或密码错误!";
log.debug("处理BadCredentialsException:{}", message);
return JsonResult.fail(ServiceCode.ERR_UNAUTHORIZED, message);
}
@ExceptionHandler
public JsonResult<Void> handleDisabledException(DisabledException e) {
String message = "登录失败,此账号已禁用!";
log.debug("处理DisabledException:{}", message);
return JsonResult.fail(ServiceCode.ERR_UNAUTHORIZED_DISABLED, message);
}
@ExceptionHandler
public JsonResult<Void> handleAccessDeniedException(AccessDeniedException e) {
String message = "访问失败,当前登录的账号无此权限!";
log.debug("处理AccessDeniedException:{}", message);
return JsonResult.fail(ServiceCode.ERR_FORBIDDEN, message);
}
另外,在解析JWT的过程中,也可能出现异常,由于解析JWT是在过滤器中进行的,如果出现异常,不会被统一处理异常的机制获取得到(因为过滤器执行的时间点太早),所以,只能在过滤器中自行处理异常,例如:
//设置响应结果的文档类型
response.setContentType("application/json; charset=utf-8");
// 尝试解析JWT
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
} catch (MalformedJwtException e) {
log.warn("解析JWT失败:{}:{}", e.getClass().getName(), e.getMessage());
JsonResult<Void> jsonResult = JsonResult.fail(
ServiceCode.ERR_JWT_PARSE, "无法获取到有效的登录信息,请重新登录!");
String jsonResultString = JSON.toJSONString(jsonResult);
PrintWriter writer = response.getWriter();
writer.println(jsonResultString);
writer.close();
return;
} catch (SignatureException e) {
log.warn("解析JWT失败:{}:{}", e.getClass().getName(), e.getMessage());
JsonResult<Void> jsonResult = JsonResult.fail(
ServiceCode.ERR_JWT_PARSE, "无法获取到有效的登录信息,请重新登录!");
String jsonResultString = JSON.toJSONString(jsonResult);
PrintWriter writer = response.getWriter();
writer.println(jsonResultString);
writer.close();
return;
} catch (ExpiredJwtException e) {
log.warn("解析JWT失败:{}:{}", e.getClass().getName(), e.getMessage());
JsonResult<Void> jsonResult = JsonResult.fail(
ServiceCode.ERR_JWT_EXPIRED, "登录信息已过期,请重新登录!");
String jsonResultString = JSON.toJSONString(jsonResult);
PrintWriter writer = response.getWriter();
writer.println(jsonResultString);
writer.close();
return;
} catch (Throwable e) {
log.warn("解析JWT失败:{}:{}", e.getClass().getName(), e.getMessage());
JsonResult<Void> jsonResult = JsonResult.fail(
ServiceCode.ERR_JWT_PARSE, "无法获取到有效的登录信息,请重新登录!");
String jsonResultString = JSON.toJSONString(jsonResult);
PrintWriter writer = response.getWriter();
writer.println(jsonResultString);
writer.close();
return;
}
总结
提示:这里对文章进行总结:
OK,至此整个通过Spring security处理开发过程中用户认证和授权的流程结束。
版权声明:本文为weixin_43816557原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。