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

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

1.Token.java

 package com.tixa.wedding.util;

 import java.io.Serializable;

 public class Token implements Serializable {

     /**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = -754659525548951914L;
private String signature;
private long timestamp; public Token(String signature, long timestamp) {
if (signature == null)
throw new IllegalArgumentException("signature can not be null"); this.timestamp = timestamp;
this.signature = signature;
} public Token(String signature) {
if (signature == null)
throw new IllegalArgumentException("signature can not be null"); this.signature = signature;
} /**
* Returns a string containing the unique signatureentifier assigned to this token.
*/
public String getSignature() {
return signature;
} public long getTimestamp() {
return timestamp;
} /**
* timestamp 不予考虑, 因为就算 timestamp 不同也认为是相同的 token.
*/
public int hashCode() {
return signature.hashCode();
} public boolean equals(Object object) {
if (object instanceof Token)
return ((Token)object).signature.equals(this.signature);
return false;
} @Override
public String toString() {
return "Token [signature=" + signature + ", timestamp=" + timestamp
+ "]";
} }

2.TokenUtil.java

 package com.tixa.wedding.util;

 import java.security.MessageDigest;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; public class TokenUtil { private static final int INTERVAL = 7;// token过期时间间隔 天
private static final String YAN = "testMRf1$789787aadfjkds//*-+'[]jfeu;384785*^*&%^%$%";// 加盐
private static final int HOUR = 3;// 检查token过期线程执行时间 时 private static Logger logger = Logger.getLogger("visit"); private static Map<Integer, Token> tokenMap = new HashMap<Integer, Token>();
private static TokenUtil tokenUtil = null;
static ScheduledExecutorService scheduler =Executors.newSingleThreadScheduledExecutor(); static {
logger.info("\n===============进入TokenUtil静态代码块==================");
listenTask();
} public static TokenUtil getTokenUtil() {
if (tokenUtil == null) {
synInit();
} return tokenUtil;
} private static synchronized void synInit() {
if (tokenUtil == null) {
tokenUtil = new TokenUtil();
}
} public TokenUtil() {
} public static Map<Integer, Token> getTokenMap() {
return tokenMap;
} /**
* 产生一个token
*/
public static Token generateToken(String uniq,int id) {
Token token = new Token(MD5(System.currentTimeMillis()+YAN+uniq+id), System.currentTimeMillis());
synchronized (tokenMap) {
tokenMap.put(id, token);
}
return token;
} /**
* @Title: removeToken
* @Description: 去除token
* @param @param nonce
* @param @return 参数
* @return boolean 返回类型
*/
public static boolean removeToken(int id) {
synchronized (tokenMap) {
tokenMap.remove(id);
logger.info(tokenMap.get(id) == null ? "\n=========已注销========": "\n++++++++注销失败+++++++++++++++");
}
return true;
} /**
* @Title: volidateToken
* @Description: 校验token
* @param @param signature
* @param @param nonce
* @param @return 参数
* @return boolean 返回类型
*/
public static boolean volidateToken(String signature, int id) {
boolean flag = false;
Token token = (Token) tokenMap.get(id);
if (token != null && token.getSignature().equals(signature)) {
logger.info("\n=====已在线=======");
flag = true;
} return flag;
} /**
*
* @Title: MD5
* @Description: 加密
* @param @param s
* @param @return 参数
* @return String 返回类型
*/
public final static String MD5(String s) {
try {
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
return byte2hex(mdInst.digest());
} catch (Exception e) {
e.printStackTrace();
return null;
}
} /**
* 将字节数组转换成16进制字符串
* @param b
* @return
*/
private static String byte2hex(byte[] b) {
StringBuilder sbDes = new StringBuilder();
String tmp = null;
for (int i = 0; i < b.length; i++) {
tmp = (Integer.toHexString(b[i] & 0xFF));
if (tmp.length() == 1) {
sbDes.append("0");
}
sbDes.append(tmp);
}
return sbDes.toString();
} /**
* @Title: listenTask
* @Description: 定时执行token过期清除任务
* @param 参数
* @return void 返回类型
*/
public static void listenTask(){
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
//定制每天的HOUR点,从明天开始
calendar.set(year, month, day+1, HOUR, 0, 0);
// calendar.set(year, month, day, 17, 11, 40);
Date date = calendar.getTime(); scheduler.scheduleAtFixedRate( new ListenToken(), (date.getTime()-System.currentTimeMillis())/1000, 60*60*24, TimeUnit.SECONDS);
} /**
* @ClassName: ListenToken
* @Description: 监听token过期线程runnable实现
* @author mrf
* @date 2015-10-21 下午02:22:24
*
*/
static class ListenToken implements Runnable {
public ListenToken() {
super();
} public void run() {
logger.info("\n**************************执行监听token列表****************************");
try {
synchronized (tokenMap) {
for (int i = 0; i < 5; i++) {
if (tokenMap != null && !tokenMap.isEmpty()) {
for (Entry<Integer, Token> entry : tokenMap.entrySet()) {
Token token = (Token) entry.getValue();
logger.info("\n==============已登录用户有:"+entry + "=====================");
// try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}
int interval = (int) ((System.currentTimeMillis() - token.getTimestamp()) / 1000 / 60 / 60 / 24);
if (interval > INTERVAL) {
tokenMap.remove(entry.getKey());
logger.info("\n==============移除token:" + entry+ "=====================");
} }
}
} }
} catch (Exception e) {
logger.error("token监听线程错误:"+e.getMessage());
e.printStackTrace();
}
}
} public static void main(String[] args) {
System.out.println(generateToken( "s",1));
System.out.println(generateToken( "q",1));
System.out.println(generateToken( "s3",2));
System.out.println(generateToken( "s4",3));
System.out.println(removeToken(3));
System.out.println(getTokenMap());
} }

app令牌的一个token实现的更多相关文章

  1. 在ASP.NET Core中实现一个Token base的身份认证

    注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...

  2. [转]NET Core中实现一个Token base的身份认证

    本文转自:http://www.cnblogs.com/Leo_wl/p/6077203.html 注:本文提到的代码示例下载地址> How to achieve a bearer token ...

  3. NET Core中实现一个Token base的身份认证

    NET Core中实现一个Token base的身份认证 注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and au ...

  4. Node教程——封装一个token验证器

    重要说明 这个轮子是 使用 express@5.0 + MongoDB构建起来的一个 node后台通用的验证器,里面主要讲的就是使用jwt,token进行验证,当然你想使用session也没问题,但是 ...

  5. App接口设计之token的php实现

    为了保证移动端和服务端数据传输相对安全,需要对接口进行加密传输. 一.ttoken的设计目的:  因为APP端没有和PC端一样的session机制,所以无法判断用户是否登陆,以及无法保持用户状态,所以 ...

  6. Android 一个app启动另一个app

    最近,一个app启动另一个app,这个玩法挺火的嘛,有没有试过更新QQ到5.1版本,QQ的健康里面就可以添加其他app,实现从QQ跳转到其他app应用.这个挺好玩的,一下子带来了多少流量啊. 一.先来 ...

  7. android一个app打开另一个app的指定页面

    一个app打开另一个app的指定页面方法 有以下几种 1.通过包名.类名 2.通过intent的 action 3.通过Url 方案1. ComponentName componentName = n ...

  8. 看我如何未授权登陆某APP任意用户(token泄露实例)

    转载:https://www.nosafe.org/thread-333-1-1.html  先来看看这个.   首先,我在登陆时候截取返回包修改id值是无效的,因为有一个token验证,经过多次登陆 ...

  9. “数学口袋精灵”App的第一个Sprint计划(总结)

    “数学口袋精灵”App的第一个Sprint计划 ——11.20  星期五(第十天)第一次Sprint计划结束   第一阶段Sprint的目标以及完成情况: 时间:11月11号~11月20号(10天) ...

随机推荐

  1. asp.net WebApi and protobuff

    protobuff 是谷歌开发的,在性能上要比Json xml好很多,对性能要求比较高的时候这个是一个不错的选择,但是这个目前只是一个序列化反序列化的东西,以前原生的只有几种语言的现在在github ...

  2. Spring RabbitMq概述

    Spring AMQP consists of a handful of modules, each represented by a JAR in the distribution. These m ...

  3. 【情人节来一发】网站添加QQ客服功能

    今年的元宵节遇到情人节,挺不自量力的,呵呵,开篇给各位讲个段子,早上一美女同学在空间发说说道:“开工大吉 起床啦,卖元宵,卖玫瑰,卖避孕套啦-有木有一起去发财的小伙伴?Let’s go…”,对于此种长 ...

  4. 那些VisualStudio隐藏的调试功能

    VisualStudio是一个强大的调试工具,里面很多隐藏功能少有人问津,但是在特定场景可以节省你很多时间,本文主要介绍一些VisualStudio调试相关的隐藏功能,欢迎大家补充. 运行到指针(Ru ...

  5. 走进AngularJs(四)自定义指令----(中)

    上一篇简单介绍了自定义一个指令的几个简单参数,restrict.template.templateUrl.replace.transclude,这几个理解起来相对容易很多,因为它们只涉及到了表现,而没 ...

  6. FusionCharts简单教程(八)-----使用网格组件

            有时候我们会觉得使用图像不够直接,对于数据的显示没有表格那样直接明了.所以这里就介绍如何使用网格组件.将网格与图像结合起来.网格组件能够将FusionCharts中的单序列数据以列表的 ...

  7. CocoSocket开源下载与编写经验分享

    CocoSocket分享 cocos2dx 3.1都出了,但依然没有发现与它原生的SOCKET支持,于是,这几天在家,手工撸了一个. 目前版本对IOS,ANDROID,WINDOWS支持良好.且为异步 ...

  8. PS 多次剪裁同一图片

    一个图品里面有两个小图,要分别抠出来. 我以前的做法是,先扣一个,重新打开文件,再扣另外一个. 今天发现一个简单的办法,不用重新打开文件. 就是在扣完第一个的时候,打开历史记录面板,双击 打开 动作, ...

  9. CSS的样式表基本概念

    一.样式表分类 1.内联样式表 <p style="fint-size:24px;">直接在标签内部进行样式设置</style> 2.内嵌样式表 <h ...

  10. CAR

    24.编写一个Car类,具有String类型的属性品牌,具有功能drive: 定义其子类Aodi和Benchi,具有属性:价格.型号:具有功能:变速: 定义主类E,在其main方法中分别创建Aodi和 ...