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博客园博客,原文链接:http://www.cnblogs.com/woshimrf/p/4943339.html,如需转载请自行联系原作者