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