Java自定义注解实现权限管理

一、定义权限注解

@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 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 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 authList, AuthorityAnnotation auth) {
        if (!CollectionUtils.isEmpty(authList)) {
            for (AuthorityAnnotationEnums authEnum : auth.value()) {
                if (authList.contains(authEnum.name())) {
                    return true;
                }
            }
        }
        return false;
    }

    public  void responseJsonMsg(HttpServletResponse response, ResultData resultData) {
        try {
            response.setContentType("application/json");
            response.setStatus(resultData.getStatus());
            response.setCharacterEncoding("UTF-8");
            Map 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

https://blog.csdn.net/kingwinstar/article/details/123089130

你可能感兴趣的:(Java自定义注解实现权限管理)