app令牌的一个token实现

简介: app登陆验证不能使用session来判断了。然后查资料都说用令牌,没找到合适的方法,我的眼界太小。另外,越来越感觉基础的重要,比如,session是什么,我竟无言以对。不知道session是什么,怎么来做验证呢。

app登陆验证不能使用session来判断了。然后查资料都说用令牌,没找到合适的方法,我的眼界太小。另外,越来越感觉基础的重要,比如,session是什么,我竟无言以对。不知道session是什么,怎么来做验证呢。然后就关于类的加载和销毁,等。我需要重新看下java基础了。

这里,我定义了一个token类来存储token。就是一个字符串+创建的时间戳。然后定义一个管理类来维护token。简单的实现了,但还有很多问题。比如,我对session的理解(是否可以放session,放session之后什么状态),比如这定义的这个类在调用的时候加载,在不用的时间结束,而我希望一直存在,这个维护类怎么确保存在,这是类的声明周期问题,比如加载到内存和缓存的实现,缓存用的太少。

1.Token.java

 1 package com.tixa.wedding.util;
 2 
 3 import java.io.Serializable;
 4 
 5 public class Token implements Serializable {
 6     
 7     /** 
 8     * @Fields serialVersionUID : TODO
 9     */ 
10     private static final long serialVersionUID = -754659525548951914L;
11     private String signature;
12     private long timestamp;
13     
14     public Token(String signature, long timestamp) {
15         if (signature == null)
16             throw new IllegalArgumentException("signature can not be null");
17         
18         this.timestamp = timestamp;
19         this.signature = signature;
20     }
21     
22     public Token(String signature) {
23         if (signature == null)
24             throw new IllegalArgumentException("signature can not be null");
25         
26         this.signature = signature;
27     }
28     
29     /**
30      * Returns a string containing the unique signatureentifier assigned to this token.
31      */
32     public String getSignature() {
33         return signature;
34     }
35     
36     public long getTimestamp() {
37         return timestamp;
38     }
39     
40     /**
41      * timestamp 不予考虑, 因为就算 timestamp 不同也认为是相同的 token.
42      */
43     public int hashCode() {
44         return signature.hashCode();
45     }
46     
47     public boolean equals(Object object) {
48         if (object instanceof Token)
49             return ((Token)object).signature.equals(this.signature);
50         return false;
51     }
52 
53     @Override
54     public String toString() {
55         return "Token [signature=" + signature + ", timestamp=" + timestamp
56                 + "]";
57     }
58     
59     
60 }

 

2.TokenUtil.java

  1 package com.tixa.wedding.util;
  2 
  3 import java.security.MessageDigest;
  4 import java.util.Calendar;
  5 import java.util.Date;
  6 import java.util.HashMap;
  7 import java.util.Map;
  8 import java.util.Map.Entry;
  9 import java.util.concurrent.Executors;
 10 import java.util.concurrent.ScheduledExecutorService;
 11 import java.util.concurrent.TimeUnit;
 12 
 13 import org.apache.log4j.Logger;
 14 
 15 
 16 
 17 public class TokenUtil {
 18 
 19     private static final int INTERVAL = 7;// token过期时间间隔 天
 20     private static final String YAN = "testMRf1$789787aadfjkds//*-+'[]jfeu;384785*^*&%^%$%";// 加盐
 21     private static final int HOUR = 3;// 检查token过期线程执行时间 时
 22     
 23     private static Logger logger = Logger.getLogger("visit");
 24 
 25     private static Map<Integer, Token> tokenMap = new HashMap<Integer, Token>();
 26     private static TokenUtil tokenUtil = null;
 27     static ScheduledExecutorService scheduler =Executors.newSingleThreadScheduledExecutor(); 
 28 
 29     static {
 30         logger.info("\n===============进入TokenUtil静态代码块==================");
 31         listenTask();
 32     }
 33     
 34 
 35     public static TokenUtil getTokenUtil() {
 36         if (tokenUtil == null) {
 37             synInit();
 38         }
 39 
 40         return tokenUtil;
 41     }
 42 
 43     private static synchronized void synInit() {
 44         if (tokenUtil == null) {
 45             tokenUtil = new TokenUtil();
 46         }
 47     }
 48 
 49     public TokenUtil() {
 50     }
 51     
 52     
 53 
 54     public static Map<Integer, Token> getTokenMap() {
 55         return tokenMap;
 56     }
 57 
 58     /**
 59      * 产生一个token
 60      */
 61     public static Token generateToken(String uniq,int id) {
 62         Token token = new Token(MD5(System.currentTimeMillis()+YAN+uniq+id), System.currentTimeMillis());
 63         synchronized (tokenMap) {
 64             tokenMap.put(id, token);
 65         }
 66         return token;
 67     }
 68 
 69 
 70     /**
 71      * @Title: removeToken
 72      * @Description: 去除token
 73      * @param @param nonce
 74      * @param @return 参数
 75      * @return boolean 返回类型
 76      */
 77     public static boolean removeToken(int id) {
 78         synchronized (tokenMap) {
 79             tokenMap.remove(id);
 80             logger.info(tokenMap.get(id) == null ? "\n=========已注销========": "\n++++++++注销失败+++++++++++++++");
 81         }
 82         return true;
 83     }
 84 
 85     /**
 86      * @Title: volidateToken
 87      * @Description: 校验token
 88      * @param @param signature
 89      * @param @param nonce
 90      * @param @return 参数
 91      * @return boolean 返回类型
 92      */
 93     public static boolean volidateToken(String signature, int id) {
 94         boolean flag = false;
 95         Token token = (Token) tokenMap.get(id);
 96         if (token != null && token.getSignature().equals(signature)) {
 97             logger.info("\n=====已在线=======");
 98             flag = true;
 99         }
100 
101         return flag;
102     }
103     
104     /**
105      * 
106      * @Title: MD5
107      * @Description: 加密
108      * @param @param s
109      * @param @return 参数
110      * @return String 返回类型
111      */
112     public final static String MD5(String s) {
113         try {
114             byte[] btInput = s.getBytes();
115             // 获得MD5摘要算法的 MessageDigest 对象
116             MessageDigest mdInst = MessageDigest.getInstance("MD5");
117             // 使用指定的字节更新摘要
118             mdInst.update(btInput);
119             // 获得密文
120             return byte2hex(mdInst.digest());
121         } catch (Exception e) {
122             e.printStackTrace();
123             return null;
124         }
125     }
126 
127     /**
128      * 将字节数组转换成16进制字符串
129      * @param b
130      * @return
131      */
132     private static String byte2hex(byte[] b) {
133         StringBuilder sbDes = new StringBuilder();
134         String tmp = null;
135         for (int i = 0; i < b.length; i++) {
136             tmp = (Integer.toHexString(b[i] & 0xFF));
137             if (tmp.length() == 1) {
138                 sbDes.append("0");
139             }
140             sbDes.append(tmp);
141         }
142         return sbDes.toString();
143     }
144     
145     /**
146     * @Title: listenTask 
147     * @Description: 定时执行token过期清除任务
148     * @param     参数
149     * @return void    返回类型
150      */
151     public static void listenTask(){
152         Calendar calendar = Calendar.getInstance();
153         int year = calendar.get(Calendar.YEAR);
154         int month = calendar.get(Calendar.MONTH);
155         int day = calendar.get(Calendar.DAY_OF_MONTH);
156         //定制每天的HOUR点,从明天开始
157         calendar.set(year, month, day+1, HOUR, 0, 0);
158        // calendar.set(year, month, day, 17, 11, 40);
159         Date date = calendar.getTime();
160         
161         scheduler.scheduleAtFixedRate( new ListenToken(), (date.getTime()-System.currentTimeMillis())/1000, 60*60*24, TimeUnit.SECONDS);
162     }
163     
164     
165 
166     /**
167      * @ClassName: ListenToken
168      * @Description: 监听token过期线程runnable实现
169      * @author mrf
170      * @date 2015-10-21 下午02:22:24
171      * 
172      */
173     static class ListenToken implements Runnable {
174         public ListenToken() {
175             super();
176         }
177 
178         public void run() {
179             logger.info("\n**************************执行监听token列表****************************");
180             try {
181                 synchronized (tokenMap) {
182                     for (int i = 0; i < 5; i++) {
183                         if (tokenMap != null && !tokenMap.isEmpty()) {
184                             for (Entry<Integer, Token> entry : tokenMap.entrySet()) {
185                                 Token token = (Token) entry.getValue();
186                                 logger.info("\n==============已登录用户有:"+entry + "=====================");
187 //                            try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
188                                 int interval = (int) ((System.currentTimeMillis() - token.getTimestamp()) / 1000 / 60 / 60 / 24);
189                                 if (interval > INTERVAL) {
190                                     tokenMap.remove(entry.getKey());
191                                     logger.info("\n==============移除token:" + entry+ "=====================");
192                                 }
193 
194                             }
195                         }
196                     }
197                     
198                 }
199             } catch (Exception e) {
200                 logger.error("token监听线程错误:"+e.getMessage());
201                 e.printStackTrace();
202             }
203         }
204     }
205     
206      
207 
208     public static void main(String[] args) {
209         System.out.println(generateToken( "s",1));
210         System.out.println(generateToken( "q",1));
211         System.out.println(generateToken( "s3",2));
212         System.out.println(generateToken( "s4",3));
213         System.out.println(removeToken(3));
214         System.out.println(getTokenMap());
215     }
216 
217 }
218 
219  

 





唯有不断学习方能改变! -- Ryan Miao
目录
相关文章
|
2天前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
3月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
869 1
|
3天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
4天前
|
Dart 前端开发 架构师
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
【01】vs-code如何配置flutter环境-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈-供大大的学习提升
|
19天前
|
开发框架 小程序 前端开发
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
148 18
|
16天前
|
JSON 供应链 搜索推荐
淘宝APP分类API接口:开发、运用与收益全解析
淘宝APP作为国内领先的购物平台,拥有丰富的商品资源和庞大的用户群体。分类API接口是实现商品分类管理、查询及个性化推荐的关键工具。通过开发和使用该接口,商家可以构建分类树、进行商品查询与搜索、提供个性化推荐,从而提高销售额、增加商品曝光、提升用户体验并降低运营成本。此外,它还能帮助拓展业务范围,满足用户的多样化需求,推动电商业务的发展和创新。
42 5
|
15天前
|
移动开发 安全 搜索推荐
圈子社交系统APP,同城本地圈子论坛开发,让身边的人沟通更加紧密
圈子社交系统APP是一款基于社交网络的移动应用,用户可创建、加入和管理兴趣圈子。主要功能包括:动态分享与交流、实时聊天、会员体系与身份认证、活动策划等。该APP注重个性化定制、社交关系深化、隐私安全及跨平台互联,提供丰富的社交体验。
|
19天前
鸿蒙语言开发 几十套鸿蒙ArkTs app毕业设计及课程作业
鸿蒙语言开发 几十套鸿蒙ArkTs app毕业设计及课程作业
26 1
|
27天前
|
JSON 缓存 前端开发
HarmonyOS NEXT 5.0鸿蒙开发一套影院APP(附带源码)
本项目基于HarmonyOS NEXT 5.0开发了一款影院应用程序,主要实现了电影和影院信息的展示功能。应用包括首页、电影列表、影院列表等模块。首页包含轮播图与正在热映及即将上映的电影切换显示;电影列表模块通过API获取电影数据并以网格形式展示,用户可以查看电影详情;影院列表则允许用户选择城市后查看对应影院信息,并支持城市选择弹窗。此外,项目中还集成了Axios用于网络请求,并进行了二次封装以简化接口调用流程,同时添加了请求和响应拦截器来处理通用逻辑。整体代码结构清晰,使用了组件化开发方式,便于维护和扩展。 该简介概括了提供的内容,但请注意实际开发中还需考虑UI优化、性能提升等方面的工作。
91 11
|
25天前
|
前端开发 数据库 UED
uniapp开发,前后端分离的陪玩系统优势,陪玩app功能特点,线上聊天线下陪玩,只要4800
前后端分离的陪玩系统将前端(用户界面)和后端(服务器逻辑)分开开发,前者负责页面渲染与用户交互,后者处理数据并提供接口。该架构提高开发效率、优化用户体验、增强可扩展性和稳定性,降低维护成本,提升安全性。玩家可发布陪玩需求,陪玩人员发布服务信息,支持在线聊天、预约及线下陪玩功能,满足多样化需求。[演示链接](https://www.51duoke.cn/games/?id=7)

热门文章

最新文章