app令牌的一个token实现
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实现的更多相关文章
- 在ASP.NET Core中实现一个Token base的身份认证
注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...
- [转]NET Core中实现一个Token base的身份认证
本文转自:http://www.cnblogs.com/Leo_wl/p/6077203.html 注:本文提到的代码示例下载地址> How to achieve a bearer token ...
- NET Core中实现一个Token base的身份认证
NET Core中实现一个Token base的身份认证 注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and au ...
- Node教程——封装一个token验证器
重要说明 这个轮子是 使用 express@5.0 + MongoDB构建起来的一个 node后台通用的验证器,里面主要讲的就是使用jwt,token进行验证,当然你想使用session也没问题,但是 ...
- App接口设计之token的php实现
为了保证移动端和服务端数据传输相对安全,需要对接口进行加密传输. 一.ttoken的设计目的: 因为APP端没有和PC端一样的session机制,所以无法判断用户是否登陆,以及无法保持用户状态,所以 ...
- Android 一个app启动另一个app
最近,一个app启动另一个app,这个玩法挺火的嘛,有没有试过更新QQ到5.1版本,QQ的健康里面就可以添加其他app,实现从QQ跳转到其他app应用.这个挺好玩的,一下子带来了多少流量啊. 一.先来 ...
- android一个app打开另一个app的指定页面
一个app打开另一个app的指定页面方法 有以下几种 1.通过包名.类名 2.通过intent的 action 3.通过Url 方案1. ComponentName componentName = n ...
- 看我如何未授权登陆某APP任意用户(token泄露实例)
转载:https://www.nosafe.org/thread-333-1-1.html 先来看看这个. 首先,我在登陆时候截取返回包修改id值是无效的,因为有一个token验证,经过多次登陆 ...
- “数学口袋精灵”App的第一个Sprint计划(总结)
“数学口袋精灵”App的第一个Sprint计划 ——11.20 星期五(第十天)第一次Sprint计划结束 第一阶段Sprint的目标以及完成情况: 时间:11月11号~11月20号(10天) ...
随机推荐
- 解剖SQLSERVER 第三篇 数据类型的实现(译)
解剖SQLSERVER 第三篇 数据类型的实现(译) http://improve.dk/implementing-data-types-in-orcamdf/ 实现对SQLSERVER数据类型的解 ...
- [C#进阶系列]专题一:深入解析深拷贝和浅拷贝
一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...
- SQL SERVER 内存学习系列(一)
最近帮客户解决发布订阅的问题时,突然遇到这样一个问题发布订阅中报下面的错误,另外执行alter table 操作时也会报错 : 问题很奇怪发布订阅和CLR有什么关系?memtoleave内存是个啥?回 ...
- 设计模式之美:Product Trader(操盘手)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Product Trader 的示例实现. 意图 使客户程序可以通过命名抽象超类和给定规约来创建对象. Product Trad ...
- Wix 安装部署教程(十六) -- 自动生成多语言文件
因为持续集成需要,所有项目编译完之后生成一个多语言的安装包.之前生成mst文件都是手动操作,而且mst文件必须每次重新和新的安装包“关联”,否则中文的安装包去调用英文的资源的时候就会报类似于“类型转换 ...
- C#反射基础知识和实战应用
首先来说一下什么是反射? 反射提供了封装程序集.模块和类型的对象(Type类型) 可以使用反射动态的创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后,可以调用类型的方法或访问其字段和 ...
- JITCompiler、NGen.exe及.NET Native
一.JITCompiler 如你所知,JIT(just-in-time或“即时”)编译器是CLR的重要组件,它的职责是将IL转换成本地cpu指令. <<CLR via C#>> ...
- 趣味C程序-HelloWord
说明:刚才写了一个基础的helloWord程序(很早以前从其他地方收集的.),本以为群里面的人是可以答对了,但是我错了,没有人.他们的错误往往被程序的外表给蒙蔽了. 很多人的回答是0.如果你仔细看的话 ...
- Git Day02,工作区,暂存区,回退,删除文件
1st,工作区回退:2st,暂存区回退:3rd,删除文件:
- Node Express 4.0 安装
前言 今天想要用nodejs 写个后台服务,很久之前看过node express 框架,可真当向下手安装的时候,发现好多命令都不记得了.写完后台服务,没事了,总结了下安装过程,记录一下,以便以后查阅方 ...