zoukankan      html  css  js  c++  java
  • app令牌的一个token实现

    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("
    ===============进入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 ? "
    =========已注销========": "
    ++++++++注销失败+++++++++++++++");
     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("
    =====已在线=======");
     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("
    **************************执行监听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("
    ==============已登录用户有:"+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("
    ==============移除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  
  • 相关阅读:
    查询表中列转换为json
    查看死锁
    利用vba将excel中的图片链接直接转换为图片
    npoi与memcached中的ICSharpCode.SharpZipLib版本冲突的解决方案
    网页爬虫的一些笔记
    从远程服务器数据库中同步数据到本地数据库 sql server 2008 开启分布
    配置ST3在浏览器中打开
    在 sublime text 3 中添加 Emmet (ZenCoding)
    win2008远程桌面会话数增加
    20150728月度会议
  • 原文地址:https://www.cnblogs.com/woshimrf/p/4943339.html
Copyright © 2011-2022 走看看