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天) ...
随机推荐
- linux配置java环境变量(详细) -copy
一. 解压安装jdk 在shell终端下进入jdk-6u14-linux-i586.bin文件所在目录, 执行命令 ./jdk-6u14-linux-i586.bin 这时会出现一段协议,连继敲回车, ...
- 最快让你上手ReactiveCocoa之进阶篇
前言 由于时间的问题,暂且只更新这么多了,后续还会持续更新本文<最快让你上手ReactiveCocoa之进阶篇>,目前只是简短的介绍了些RAC核心的一些方法,后续还需要加上MVVM+Rea ...
- addEventListener、attachEvent、cancelBubble兼容性随笔
一.前言 1. element.addEventListener(eventType, handler, capture); (1)参数eventType是要注册句柄的事件类型名. (2)参数hand ...
- phoenix 开发API系列(三)phoenix api 结合数据库
概述 介绍了 api 的各种写法之后,下面介绍构建 api 时与数据库连接的方式. 注 下面使用的工程的完整代码已经公开在: http://git.oschina.net/wangyubin/phoe ...
- 利用IIS应用请求转发ARR实现IIS和tomcat整合共用80端口
现在网上流传的实现iis和tomcat共享80端口的方法是基于isapi_redirect插件实现的, 我的实现方法不同, 原理相似,具有更好的优点. 先说下基于isapi_redirect缺点,ja ...
- AIX 文件 打包 与 压缩 tar gzip compress 的使用
今天在Aix用tar -cvf 备份,打成tar包,占有硬盘空间过大,没有压缩比, 尝试使用tar -zcvf linux系统下可以用-z 命令 (z 用gzip来压缩/解压缩文件,加上该选项后可以 ...
- UWP开发随笔——UWP新控件!AutoSuggestBox!
摘要 要开发一款优秀的application,控件肯定是必不可少的,uwp就为开发者提供了各种各样的系统控件,AutoSuggestBox就是uwp极具特色的控件之一,也是相对于之前win8.1的ua ...
- easy-ui JOB 及 小记录
$:获取 $.ajax({ type: "POST" , url: "" , cont ...
- Android消息机制
每一个Android应用在启动的时候都会创建一个线程,这个线程被称为主线程或者UI线程,Android应用的所有操作默认都会运行在这个线程中. 但是当我们想要进行数据请求,图片下载,或者其他耗时操作时 ...
- ASP.NET将原始图片按照指定尺寸等比例缩放显示图片
网站上可能会有很多图片,比如产品图片等,而且他们可能大小不一,宽度和高度也不一定一样,有的很大有的很小.如果放在一张网页上,可能会破坏版面,但是如果强制让他们按照指定的宽度和高度显示,因为比例不同还会 ...