美文网首页Java
Java自定义注解实现权限管理

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

作者: 小波同学 | 来源:发表于2022-05-18 20:02 被阅读0次

    一、定义权限注解

    @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

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

    相关文章

      网友评论

        本文标题:Java自定义注解实现权限管理

        本文链接:https://www.haomeiwen.com/subject/hmnaurtx.html