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. Android度量单位说明(DIP,DP,PX,SP) (转帖)

    (一)概念 dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不 ...

  2. Ubuntu全新安装firefox最新版本

    Ubuntu默认安装firefox,但是自带的软件仓库是不会随firefox更新的,我在使用中老是提示flash插件需要激活,提示中可选的解决方式有三种 1.更新flash插件,但是跳转到adobe的 ...

  3. jQuery Ready 与 Window onload 的区别(转)

    “我们都知道,很多时候,在页面加载完后都需要做一些相应的初始化动作.例如,运行某些js特效,设置表单等等.怎么知道页面加载完了呢?一 般情况下都是设置body标签的onload监听window的loa ...

  4. [Asp.net 开发系列之SignalR篇]专题二:使用SignalR实现酷炫端对端聊天功能

    一.引言 在前一篇文章已经详细介绍了SignalR了,并且简单介绍它在Asp.net MVC 和WPF中的应用.在上篇博文介绍的都是群发消息的实现,然而,对于SignalR是为了实时聊天而生的,自然少 ...

  5. Web前端技术研究:Css hack技术---令人沮丧的技术

    我最近想好好整理下csshack技术,但是结果很沮丧,下面我将我最初写的笔记和大家分享下. 我在单位整理的研究笔记: 不同的浏览器对某些CSS代码解析会存在一定的差异,因此就会导致不同浏览器下给用户展 ...

  6. JavaScript思维导图—Window对象

    JavaScript思维导图-来自@王子墨http://julying.com/blog/the-features-of-javascript-language-summary-maps/

  7. 学习Scala01 环境安装

    Scala是一门运行在jvm上的多范式语言,作为一个java程序员,使用Scala来写写程序,既不用担心会没有java强大的库支持,又能快速地写出简短强悍的代码,除此之外scala还为我们提供了强大的 ...

  8. jQuery为哪般去掉了浏览器检测

    由于做HTML5相关的项目,许多前卫时髦的前端技术就需要考虑一下IE是否支持.要是在以前,可以很方便地调用jQuery的jQuery.browser来实现. If(jQuery.browser.msi ...

  9. jQuery实现放大镜效果

    1.1.1 摘要 相信大家都见过或使用过放大镜效果,甚至实现过该效果,它一般应用于放大查看商品图片,一些电商网站(例如:凡客,京东商城,阿里巴巴等)都有类似的图片查看效果. 在接下来的博文中,我们将向 ...

  10. 据说每个大牛、小牛都应该有自己的库——DOM处理

    这几天整理了一下思路,本来觉得DOM部分会有很多东西,但是忽然发现频繁使用的其实并不太多 class class处理部分主要有四个 hasClass:检查元素是否包含某个class addClass: ...