当前位置: 首页 > news >正文

使用Spring实现权限控制动态为注解赋值

首先这不是一个介绍或者使用SpringSecurity的博客。他是使用自定义注解和拦截器实现的权限管理(只供学习不可用于生产环境)

技术栈:

SpringBoot 2.1.6
MySQL5.7

大体思路:

  1. 使用拦截器拦截请求,在拦截器中使用 HandlerMethod 类获取当前请求方法上的自定义权限注解。判断是否有此访问权限。
  2. 动态改变注解值(实际生产环境中不同角色拥有的权限不可能一直不发生改变)
首先实现第一步:

创建两个注解

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public@interfaceMyClass{// 放置在类上}
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public@interfaceMyTest{String[]v()default{"-1"};// 防止在方法上// v() 中保存的是权限ID 默认-1 即没有任何角色可以访问}

编写一个Controller并添加注解

@RestController@RequestMapping("/myController")@MyClasspublicclassMyController{@RequestMapping("/get")@MyTest(v={"1","2","3"})// 赋值上角色ID为 1,2,3才能访问publicStringget(){return"Hello,world";}@RequestMapping("/set")@MyTestpublicStringset(){return"Hello,world";}}

编写拦截器(不要忘记使用这个拦截器)

packagecom.annie.interceptor;importcom.alibaba.fastjson.JSON;importcom.annie.annotation.MyTest;importorg.springframework.stereotype.Component;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerInterceptor;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.lang.reflect.Method;@ComponentpublicclassMyInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{HandlerMethod handlerMethod=(HandlerMethod)handler;Method method=handlerMethod.getMethod();MyTest annotation=method.getAnnotation(MyTest.class);if(annotation!=null){// 从 request 或者 session 中获取当前请求角色String roleId="1";// 假定请求角色的权限ID为1String[]v=annotation.v();// 获取权限for(String s:v){if(s.equals(roleId)){// 判断是否拥有访问权限returntrue;}}returnfalse;}returnfalse;}}

到此一个简单的权限判断就算是完成了但是我们不能预知一个方法可以使用的所有角色。所以我们要在使用一个方法让这个注解可以动态赋值。因为我们使用的是Spring框架,Spring在项目启动初期就将所有的Bean收集起来了。我们这要拿到那个容器就可以拿到当前项目中所有方法。在通过去数据库类比。为每个自定义注解动态设置值。

packagecom.annie.task;importcom.alibaba.fastjson.JSON;importcom.annie.annotation.MyClass;importcom.annie.annotation.MyTest;importorg.springframework.beans.BeansException;importorg.springframework.context.ApplicationContext;importorg.springframework.context.ApplicationContextAware;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;importjava.lang.reflect.*;importjava.util.Map;@ComponentpublicclassMyTaskimplementsApplicationContextAware{privateApplicationContext applicationContext;// 保存所有Bean的容器@Scheduled(fixedRate=1000)publicvoidtask01()throwsClassNotFoundException,NoSuchFieldException,IllegalAccessException{Map<String,Object>beansWithAnnotation=this.applicationContext.getBeansWithAnnotation(MyClass.class);for(String key:beansWithAnnotation.keySet()){// 反射获取类,这里有一个问题。我在使用 Swagger2 时添加了注解。用于Swagger2使用了动态代理我拿不到注解数据。// 于是这个我提供一个备用方案。 获取这个类的名称然后 通过 Class.forName() 获取注解值Object testController=beansWithAnnotation.get(key);Class<?>aClass=testController.getClass();Method[]methods=aClass.getDeclaredMethods();for(Method m:methods){MyTest annotation=m.getAnnotation(MyTest.class);if(annotation==null){continue;}// 获取代理处理器InvocationHandler invocationHandler=Proxy.getInvocationHandler(annotation);// 过去私有 memberValues 属性Field f=invocationHandler.getClass().getDeclaredField("memberValues");f.setAccessible(true);// 获取实例的属性mapMap<String,Object>memberValues=(Map<String,Object>)f.get(invocationHandler);// 修改属性值String arr[]={"1","2"};memberValues.put("v",arr);System.out.println(JSON.toJSONString(annotation.v()));}}}@OverridepublicvoidsetApplicationContext(ApplicationContext applicationContext)throwsBeansException{this.applicationContext=applicationContext;}}

我这里懒得获取数据库中的值进行类比。直接写的死值。
项目下载:下载


扩展内容
github
个人博客

http://www.jsqmd.com/news/1281738/

相关文章:

  • Git 快速极简图文教程 第一篇
  • 物联网设备硬件级安全方案:PIC18与SE050集成实践
  • 企业私域流量团队搭建与高效运营指南
  • HFS文件服务器:轻松搭建个人云存储与文件共享平台
  • M9A技术深度解析:基于MaaFramework的《重返未来:1999》自动化引擎
  • Serverless安全实战:从TAR依赖漏洞到10步纵深防御体系构建
  • 【C++】 unordered_map 与unordered_set
  • URP水体渲染:动态生成渐变纹理实现数据驱动颜色控制
  • hdu 5458 Stability (并查集+线段树+树链剖分(边权))
  • JavaScript笔记:BOM--event
  • AI教育培训应用如何真正提分?揭秘2024年头部机构私藏的7个数据驱动教学闭环设计
  • 终极Adobe激活解决方案:GenP 3.0完整破解指南
  • Raft 实现中的死活锁场景分析:从选举风暴到日志一致性的边缘案例集合
  • 抖音下载神器:三步搞定批量下载、无水印保存与智能管理
  • SpringDataRedis
  • Axure中文语言包:3分钟让专业原型设计工具说中文的完整指南
  • 2026 新版大庆防水补漏服务商参考|阳台渗漏修缮方案指南 - 筑宅安
  • C++11右值引用与移动语义:高性能编程的核心机制
  • 长期投资与复利效应:财富积累的核心策略
  • CentOS 7 搭建 vsftpd:匿名用户、本地用户、虚拟用户与 FTPS
  • 物联网设备安全芯片SE050与PIC18F86J10集成方案
  • FlashDB嵌入式数据库深度解析:架构设计与核心实现原理
  • AI推理成本暴跌63%的秘密:Llama 3、Qwen2、Phi-3在8卡A10 vs 2×H100真实吞吐与$每千token对比(独家压测数据)
  • 终极QQ空间说说备份神器:GetQzonehistory完整使用指南
  • Java土家文化管理平台毕业设计全栈实现方案
  • Rust 迁移 Python AI 服务的失败案例集:当性能提升不足以覆盖工程成本时
  • 如何在3分钟内免费安装开源视频下载助手:轻松保存网页视频的终极指南
  • p003基于爬虫与文本挖掘的网络舆情监控系统-flask_hive21(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • 2026实力之选:广州市南沙区宸润商行——深耕南沙三年的专业礼品回收实力公司 - 品牌发掘
  • PAT甲级 1060 Are They Equal 判断两个小数是否相等