使用spring拦截器手写权限认证框架
程序员文章站
2022-07-21 17:10:27
1、新建用户对象封装的实体类 2、使用单例模式创建用户对象的容器 3、封装成用户对象操作的工具类 4、拦截器的实现 5、把拦截器注入岛spring容器中,配置跨域,使用spring定时器,定时清除过期用户 6、测试 未做压力测试,适合做后台管理系统使用,并发高的项目慎用。 ......
1、新建用户对象封装的实体类
* * 主体类 * wmy 13:20 2019/8/15 * @param * @return **/ public class subject { private object bean; private string token; private date expired; public string gettoken() { return token; } public void settoken(string token) { this.token = token; } public date getexpired() { return expired; } public void setexpired(date expired) { this.expired = expired; } public object getbean() { return bean; } public void setbean(object bean) { this.bean = bean; } @override public string tostring() { return "subject{" + "bean=" + bean + ", token='" + token + '\'' + ", expired=" + expired + '}'; } }
2、使用单例模式创建用户对象的容器
@bean("tokens") public map<string, subject> gettokens() { map<string, subject> tokens = new hashmap<>(); return tokens; }
3、封装成用户对象操作的工具类
@component public class subjectutil implements beanfactoryaware { private static beanfactory beanfactory = null; private static string token = null; public static string gettoken() { return token; } public static void settoken(string token) { subjectutil.token = token; } @override public void setbeanfactory(beanfactory beanfactory) throws beansexception { subjectutil.beanfactory = beanfactory; } public static beanfactory getbeanfactory() { return beanfactory; } /* * 获得当前用户id * wmy 15:29 2019/8/19 * @param [] * @return java.lang.integer **/ public static integer getsubjectid() { return subjectutil.getbean(token,branduserr.class).getid(); } /* * 厂商id * wmy 9:44 2019/8/26 * @param [] * @return java.lang.integer **/ public static integer getbrandid() { return subjectutil.getbean(token,branduserr.class).getbrandid(); } /* * 获得在线用户封装 **/ public static subject getsubject(string token) { map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens"); return beans.get(token); } /* * 获得在线用户 **/ public static object getbean(string token) { map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens"); subject subject = beans.get(token); if (subject != null) { return subject.getbean(); } return null; } //获得在线用户 public static final <t> t getbean(string token, class<t> clazz) { map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens"); subject subject = beans.get(token); if (subject != null) { object bean = subject.getbean(); if (clazz.isinstance(bean)) { return clazz.cast(bean); } } return null; } /* * 添加在线用户 **/ public static void addtokenbean(string token, object bean, date expired) { object beans = beanfactory.getbean("tokens"); if (beans != null && beans instanceof map) { map<string, subject> map = (map<string, subject>) beans; if (!map.containskey(token)) { subject subject = new subject(); subject.setbean(bean); subject.setexpired(expired); subject.settoken(token); map.put(token, subject); } } } /* * 删除用户 **/ public static void removetokenbean(string token) { map<string, subject> beans = (map<string, subject>) beanfactory.getbean("tokens"); beans.remove(token); } /* * 获得所有在线用户 * wmy 10:53 2019/8/19 * @param [] * @return java.util.map<java.lang.string,com.raise3d.config.subject> **/ public static map<string, subject> getbeans() { object beans = beanfactory.getbean("tokens"); if (beans != null && beans instanceof map) { map<string, subject> map = (map<string, subject>) beans; return map; } return null; } /* * 清楚所有用户 * wmy 13:02 2019/8/19 * @param [] * @return void **/ public static void clear() { object beans = beanfactory.getbean("tokens"); if (beans != null && beans instanceof map) { map<string, subject> map = (map<string, subject>) beans; map.clear(); } } }
4、拦截器的实现
/* * 登录拦截器 * wmy 14:02 2019/8/19 * @param * @return **/ public class logininterceptor implements handlerinterceptor { @override public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception { if (!request.getmethod().equals("options")) { string token = request.getheader("authorization"); int verify = verify(token); if (verify == 0) { printwriter writer = response.getwriter(); writer.write(config.msg_access_denied); return false; } else if (verify == 2) { printwriter writer = response.getwriter(); writer.write(config.msg_access_expired); return false; } else if (subjectutil.gettoken() == null) { printwriter writer = response.getwriter(); writer.write(config.msg_access_denied); return false; } } return true; } @override public void posthandle(httpservletrequest request, httpservletresponse response, object handler, modelandview modelandview) throws exception { } @override public void aftercompletion(httpservletrequest request, httpservletresponse response, object handler, exception ex) throws exception { subjectutil.settoken(null); } /* * 认证方法 * wmy 11:29 2019/8/15 * @param [token] * @return java.lang.boolean **/ public synchronized int verify(string token) { if (token != null) try { subject subject = subjectutil.getsubject(token); if (subject != null) { //判断是否过期 if (subject.getexpired().gettime() + config.msg_expired < system.currenttimemillis()) { return 2; } else { if (!token.equals(subjectutil.gettoken())) { while (true) { if (subjectutil.gettoken() == null) { subjectutil.settoken(token); return 1; } system.out.println("********** token切换中 *********"); } } return 1; } } } catch (exception e) { e.printstacktrace(); } return 0; } }
5、把拦截器注入岛spring容器中,配置跨域,使用spring定时器,定时清除过期用户
@configuration @enablescheduling public class webmvcconfig extends webmvcconfigureradapter { @override public void addinterceptors(interceptorregistry registry) { registry.addinterceptor(new logininterceptor()).addpathpatterns("/**").excludepathpatterns("/branduser/login"); } @override public void addcorsmappings(corsregistry registry) { registry.addmapping("/**").allowedorigins("*"); } @bean("tokens") public map<string, subject> gettokens() { map<string, subject> tokens = new hashmap<>(); return tokens; } @scheduled(fixeddelay = 2 * 60 * 60 * 1000)//两个小时执行一次 private void expiredtokens() { map<string, subject> beans = subjectutil.getbeans(); set<string> tokens = new hashset<>(); if (beans.size() > 0) { for (string key : beans.keyset()) { if (beans.get(key).getexpired().gettime() + config.msg_expired < system.currenttimemillis()) { tokens.add(key); } } if (tokens.size() > 0) { tokens.stream().foreach(token -> subjectutil.removetokenbean(token)); } } } }
6、测试
@postmapping("/test") public result test() { string token = subjectutil.gettoken(); branduserr bean = subjectutil.getbean(token, branduserr.class); return result.ok(bean); } @postmapping("/test2") public result test2() { //subjectutil.clear(); return result.ok(subjectutil.getbean(subjectutil.gettoken())); }
未做压力测试,适合做后台管理系统使用,并发高的项目慎用。
推荐阅读
-
使用spring拦截器手写权限认证框架
-
Java Spring MVC 框架:(九)拦截器的使用
-
使用springmvc运行流程分析,手写spring框架尝试
-
spring boot框架学习8-【干货】spring boot的web开发(4)-自定义拦截器处理权限
-
使用springmvc运行流程分析,手写spring框架尝试
-
Spring Boot+shiro+redis 安全框架权限认证前后端分离【完整版】总结
-
详述 Spring MVC 框架中拦截器 Interceptor 的使用方法
-
详述 Spring MVC 框架中拦截器 Interceptor 的使用方法
-
详述 Spring MVC 框架中拦截器 Interceptor 的使用方法
-
【转】详述 Spring MVC 框架中拦截器 Interceptor 的使用方法