一、定义权限注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthorityAnnotation {
AuthorityAnnotationEnums[] value();
}
- 定义权限CODE枚举
public enum AuthorityAnnotationEnums {
ADMIN("超级权限"),
UPDATE("更新权限"),
;
private String desc;
AuthorityAnnotationEnums(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
二、增加拦截器
@Component
@Slf4j
public class AuthorityInterceptor extends ZBaseInterceptorAdapter {
@Autowired
private RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
//仅校验方法级别的Handler
if (!(handler instanceof HandlerMethod)) {
return super.preHandle(request, response, handler);
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
AuthorityAnnotation auth = handlerMethod.getMethod().getAnnotation(AuthorityAnnotation.class);
if (auth == null) {
// 如果注解为null, 说明不需要拦截, 直接放过
return true;
}
//从header中获取token
String token = request.getHeader(JwtConstants.ACCESS_TOKEN_HEADER);
//根据token从redis获取JwtInfo用户实体
JwtUserInfo jwtUserInfo = (JwtUserInfo)redisUtil.get(token);
if(jwtUserInfo == null){
log.error("用户登录拦截器校验, 从redis中获取用户信息为空, token:{}", token);
ResultData<String> resultData = ResultData.fail(JsonCommonCodeEnum.E0008.getStatus(), JsonCommonCodeEnum.E0008.getMessage(), "/login.html");
responseJsonMsg(response, resultData);
return Boolean.FALSE;
}
//用户权限数据缓存key
String authKey = RedisKeyConstant.APP_CACHE_PREFIX + jwtUserInfo.getUserId();
//获取用户缓存权限
SysAuthMenuVo authMenuVo = (SysAuthMenuVo)redisUtil.get(authKey);
//校验用户是否有权限
if (!hasAuth(authMenuVo.getAuthList(), auth)) {
log.info("用户权限校验未通过, token:{}", token);
ResultData<String> resultData = ResultData.fail(JsonCommonCodeEnum.E0007.getStatus(), JsonCommonCodeEnum.E0007.getMessage(), "/login.html");
responseJsonMsg(response, resultData);
return false;
}
return true;
} catch (Exception e) {
log.error("用户权限校验异常", e);
throw new RequestResultException("用户权限校验未通过");
}
}
/**
* 获取注解
* @param handler
* @return
*/
private AuthorityAnnotation getAnnotation(HandlerMethod handler) {
AuthorityAnnotation annotation = handler.getClass().getAnnotation(AuthorityAnnotation.class);
AuthorityAnnotation methodAnnotation = handler.getMethod().getAnnotation(AuthorityAnnotation.class);
return methodAnnotation == null ? annotation : methodAnnotation;
}
/**
* 校验权限是否匹配
* @param authList
* @param auth
* @return
*/
private boolean hasAuth(List<String> authList, AuthorityAnnotation auth) {
if (!CollectionUtils.isEmpty(authList)) {
for (AuthorityAnnotationEnums authEnum : auth.value()) {
if (authList.contains(authEnum.name())) {
return true;
}
}
}
return false;
}
public <T> void responseJsonMsg(HttpServletResponse response, ResultData<T> resultData) {
try {
response.setContentType("application/json");
response.setStatus(resultData.getStatus());
response.setCharacterEncoding("UTF-8");
Map<String, Object> result = new HashMap<>();
result.put("status", resultData.getCode());
result.put("message", resultData.getMessage());
result.put("result", resultData.getData());
String resultMsg = JSON.toJSONString(result);
response.getWriter().write(resultMsg);
} catch (IOException e) {
log.error("responseJsonMsg error,resultData:{}", JSON.toJSONString(resultData), e);
}
}
}
public enum JsonCommonCodeEnum implements JsonReturnCode {
C0000("处理成功"),
E0000("未知服务器错误"),
E0001("处理失败"),
E0002("参数不全或无效"),
E0004("服务器正忙,请稍后"),
E0005("服务器异常!"),
E0006("参数格式不符合要求"),
E0007("用户权限未通过校验"),
E0008("用户未登录"),
E0009("CSRF校验不通过"),
E0010("RSA加密校验不通过"),
E0011("上传失败!"),
E0013("上传文件大小超过最大限制!"),
E0014("excel上传异常!"),
E0016("附件为空!"),
E0017("内部访问限制"),
E0018("服务请求超时,请稍后再试"),
E0019("用户状态已更新,请重新登录"),
E0020("数据重复"),
E0021("登出【已在其他设备上登录】"),
E0022("登出【账号因长时间未操作】"),
E0023("登出【修改了密码】"),
E0024("登出【冻结】"),
E0025("登出【离职】"),
E0026("待缴费【系统使用费,首次使用系统时】"),
E0027("欠费【系统使用费】"),
E0028("续费【系统使用费】"),
E0029("账号不存在"),
E0030("手机号或密码错误"),
E0031("账号冻结"),
E0032("开启防水墙"),
E0033("登出【权限变更】"),
E0034("敏感词");
private final String msg;
private JsonCommonCodeEnum(String msg) {
this.msg = msg;
}
public String getMessage() {
return this.msg;
}
public String getStatus() {
return this.name();
}
}
三、配置拦截器
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {
@Resource
private Environment env;
@Autowired
private AuthorizationInterceptor authorizationInterceptor;
@Autowired
private AuthorityInterceptor authorityInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] swaggerExcludePathPatterns = { "/doc.html","/swagger-resources/**","/webjars/**","/v2/**"};
registry.addInterceptor(new ContextInterceptor()).addPathPatterns("/**");
if("dev".equals(env.getProperty(CommonProperties.ENV_DEPLOY))){
}else{
swaggerExcludePathPatterns = new String[0];
}
registry.addInterceptor(authorizationInterceptor)
.excludePathPatterns("/security/sysUser/logout")
.excludePathPatterns("/security/sysUser/login")
.excludePathPatterns(swaggerExcludePathPatterns)
.addPathPatterns("/**").order(-1);
//order()的值,值越小,优先级越高。不配默认是0
registry.addInterceptor(authorityInterceptor).addPathPatterns("/security/**").order(100);
}
}
参考:
https://blog.csdn.net/zzti_erlie/article/details/80881461
网友评论