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天) ...
随机推荐
- C#基于Socket的简单聊天室实践
序:实现一个基于Socket的简易的聊天室,实现的思路如下: 程序的结构:多个客户端+一个服务端,客户端都是向服务端发送消息,然后服务端转发给所有的客户端,这样形成一个简单的聊天室功能. 实现的细节: ...
- 开源库Magicodes.WeChat.SDK总体介绍
目录 1 概要 1 2 主要特点 2 3 架构图 8 3.1 构造器——WeChatSDKBuilder 8 3.2 函数管理器——WeChatF ...
- SqlServer2012 数据库的同步之发布+订阅
文章参考了百度过的文章,因为版本不同,操作中也遇到了很多问题,现在整理一下,希望对各位朋友有所帮助. 发布订阅份为两个步骤:1.发布.2订阅.首先在数据源数据库服务器上对需要同步的数据进行发布,然后在 ...
- .NET Core 1.0-最简单的Hello world控制台程序
使用任意的文本编辑软件,新建两个文件 1.Program.cs using System; using System.Collections.Generic; using System.Linq; u ...
- SQL SERVER 内存学习系列(二)-DMV查看内存信息
内存管理在SQL Server中有一个三级结构.底部是内存节点,这是最低级的分配器,用于SQL Server的内存.第二个层次是由内存Clerk组成,这是用来访问内存节点和缓存存储,缓存存储则用于缓存 ...
- Java多线程21:多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask
CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就是CyclicBarrier.CyclicBarrier从字面理解是指循环屏障,它可以协同多个线程,让多个线程在这个屏障前等待,直到 ...
- PC远程调试移动设备
我们在移动端进行前端开发时,会遇到一个让人头痛但不得不面对的问题——调试. 在 PC 机器上,我们有功能强大的 Chrome DevTools.Firebug,即便是老版本的 IE ,我们也可以安装微 ...
- java算法(二)
四.最小公倍数最大公约数问题: 分析:两个数的最小公倍数等于两个数相乘再除以他们的最大公约数,因此只要求出最大公约数就可以啦. package JingDian; public class yuebe ...
- java程序 启动时参数
iEMP34:/opt/version/lktest/b030/jre/jre_linux/bin # ./java -classpath . SysInfo Exception in threa ...
- Node.js与Sails~自定义响应体responses
回到目录 在Node.js里,你可以控制请求和响应,自己可以定义自己的响应方式,如对文本如何响应,对json如何响应,对图像流如何响应等等,而这些在Sails架构里,变得更加容易和清晰了,它位于项目的 ...