java 生成token代码_java token生成和校验的实例代码

现在越来越多的登录方式都用到了token作为用户登录令牌,所以实现了一个token生成和校验案例。

缺点:该实现方式token是存储在内存中,不适合分布式项目,如需改为分布式项目部署,可把token存储在redis中,其中的实现原理还是保持不变。

一)token编码工具类

package com.oysept.token.utils;

/**

* token编码工具类

* @author ouyangjun

*/

public class TokenEncryptUtils {

// 编码密码,可自定义

private static final String ENCODED_PASSWORD = "ouyangjun";

/**

* 编码

* @param str

* @return

*/

public static String encoded(String str) {

return strToHex(encodedString(str, ENCODED_PASSWORD));

}

/**

* 转换

* @param str

* @param password

* @return

*/

private static String encodedString(String str, String password) {

char[] pwd = password.toCharArray();

int pwdLen = pwd.length;

char[] strArray = str.toCharArray();

for (int i=0; i

strArray[i] = (char)(strArray[i] ^ pwd[i%pwdLen] ^ pwdLen);

}

return new String(strArray);

}

private static String strToHex(String s) {

return bytesToHexStr(s.getBytes());

}

private static String bytesToHexStr(byte[] bytesArray) {

StringBuilder builder = new StringBuilder();

String hexStr;

for (byte bt : bytesArray) {

hexStr = Integer.toHexString(bt & 0xFF);

if (hexStr.length() == 1) {

builder.append("0");

builder.append(hexStr);

}else{

builder.append(hexStr);

}

}

return builder.toString();

}

/**

* 解码

* @param str

* @return

*/

public static String decoded(String str) {

String hexStr = null;

try {

hexStr = hexStrToStr(str);

} catch (Exception e) {

e.printStackTrace();

}

if (hexStr != null) {

hexStr = encodedString(hexStr, ENCODED_PASSWORD);

}

return hexStr;

}

private static String hexStrToStr(String hexStr) {

return new String(hexStrToBytes(hexStr));

}

private static byte[] hexStrToBytes(String hexStr) {

String hex;

int val;

byte[] btHexStr = new byte[hexStr.length()/2];

for (int i=0; i

hex = hexStr.substring(2*i, 2*i+2);

val = Integer.valueOf(hex, 16);

btHexStr[i] = (byte) val;

}

return btHexStr;

}

}

二)token生成和校验工具类(包含main方法测试)

package com.oysept.token.utils;

import java.util.HashMap;

import java.util.Map;

import java.util.Map.Entry;

/**

* token生成和校验

* @author ouyangjun

*/

public class TokenUtils {

private static Map MAP_TOKENS = new HashMap();

private static final int VALID_TIME = 60*60*2; // token有效期(秒)

public static final String TOKEN_ERROR = "F"; // 非法

public static final String TOKEN_OVERDUE = "G"; // 过期

public static final String TOKEN_FAILURE = "S"; // 失效

/**

* 生成token,该token长度不一致,如需一致,可自行MD5或者其它方式加密一下

* 该方式的token只存在磁盘上,如果项目是分布式,最好用redis存储

* @param str: 该字符串可自定义,在校验token时要保持一致

* @return

*/

public static String getToken(String str) {

String token = TokenEncryptUtils.encoded(getCurrentTime()+","+str);

MAP_TOKENS.put(str, token);

return token;

}

/**

* 校验token的有效性

* @param token

* @return

*/

public static String checkToken(String token) {

if (token == null) {

return TOKEN_ERROR;

}

try{

String[] tArr = TokenEncryptUtils.decoded(token).split(",");

if (tArr.length != 2) {

return TOKEN_ERROR;

}

// token生成时间戳

int tokenTime = Integer.parseInt(tArr[0]);

// 当前时间戳

int currentTime = getCurrentTime();

if (currentTime-tokenTime < VALID_TIME) {

String tokenStr = tArr[1];

String mToken = MAP_TOKENS.get(tokenStr);

if (mToken == null) {

return TOKEN_OVERDUE;

} else if(!mToken.equals(token)) {

return TOKEN_FAILURE;

}

return tokenStr;

} else {

return TOKEN_OVERDUE;

}

}catch (Exception e) {

e.printStackTrace();

}

return TOKEN_ERROR;

}

/**获取当前时间戳(10位整数)*/

public static int getCurrentTime() {

return (int)(System.currentTimeMillis()/1000);

}

/**

* 移除过期的token

*/

public static void removeInvalidToken() {

int currentTime = getCurrentTime();

for (Entry entry : MAP_TOKENS.entrySet()) {

String[] tArr = TokenEncryptUtils.decoded(entry.getValue()).split(",");

int tokenTime = Integer.parseInt(tArr[0]);

if(currentTime-tokenTime > VALID_TIME){

MAP_TOKENS.remove(entry.getKey());

}

}

}

/**

* 测试

* @param args

*/

public static void main(String[] args) {

String str = "username_and_password";

// 获取token

String token = TokenUtils.getToken(str);

System.out.println("token Result: " + token);

// 校验token

String checkToken = TokenUtils.checkToken(token);

System.out.println("checkToken Result: " + checkToken);

if(str.equals(checkToken)) {

System.out.println("==>token verification succeeded!");

}

}

}

补充知识:JAVA后端生成Token(令牌),用于校验客户端,防止重复提交

1.概述:在web项目中,服务端和前端经常需要交互数据,有的时候由于网络相应慢,客户端在提交某些敏感数据(比如按照正常的业务逻辑,此份数据只能保存一份)时,如果前端多次点击提交按钮会导致提交多份数据,这种情况我们是要防止发生的。

2.解决方法:

①前端处理:在提交之后通过js立即将按钮隐藏或者置为不可用。

②后端处理:对于每次提交到后台的数据必须校验,也就是通过前端携带的令牌(一串唯一字符串)与后端校验来判断当前数据是否有效。

3.总结:第一种方法相对来说比较简单,但是安全系数不高,第二种方法从根本上解决了问题,所以我推荐第二种方法。

4.核心代码:

生成Token的工具类:

/**

* 生成Token的工具类:

*/

package red.hearing.eval.modules.token;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.util.Random;

import sun.misc.BASE64Encoder;

/**

* 生成Token的工具类

* @author zhous

* @since 2018-2-23 13:59:27

*

*/

public class TokenProccessor {

private TokenProccessor(){};

private static final TokenProccessor instance = new TokenProccessor();

public static TokenProccessor getInstance() {

return instance;

}

/**

* 生成Token

* @return

*/

public String makeToken() {

String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";

try {

MessageDigest md = MessageDigest.getInstance("md5");

byte md5[] = md.digest(token.getBytes());

BASE64Encoder encoder = new BASE64Encoder();

return encoder.encode(md5);

} catch (NoSuchAlgorithmException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

}

Token通用工具类:

/**

*

*/

package red.hearing.eval.modules.token;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;

/**

* Token的工具类

* @author zhous

* @since 2018-2-23 14:01:41

*

*/

public class TokenTools {

/**

* 生成token放入session

* @param request

* @param tokenServerkey

*/

public static void createToken(HttpServletRequest request,String tokenServerkey){

String token = TokenProccessor.getInstance().makeToken();

request.getSession().setAttribute(tokenServerkey, token);

}

/**

* 移除token

* @param request

* @param tokenServerkey

*/

public static void removeToken(HttpServletRequest request,String tokenServerkey){

request.getSession().removeAttribute(tokenServerkey);

}

/**

* 判断请求参数中的token是否和session中一致

* @param request

* @param tokenClientkey

* @param tokenServerkey

* @return

*/

public static boolean judgeTokenIsEqual(HttpServletRequest request,String tokenClientkey,String tokenServerkey){

String token_client = request.getParameter(tokenClientkey);

if(StringUtils.isEmpty(token_client)){

return false;

}

String token_server = (String) request.getSession().getAttribute(tokenServerkey);

if(StringUtils.isEmpty(token_server)){

return false;

}

if(!token_server.equals(token_client)){

return false;

}

return true;

}

}

使用方法:

①在输出前端页面的时候调用TokenTools.createToken方法,会把本次生成的token放入session中。

②然后在前端页面提交数据时从session中获取token,然后添加到要提交的数据中。

③服务端接受数据后调用judgeTokenIsEqual方法判断两个token是否一致,如果不一致则返回,不进行处理。

备注:tokenClientkey和tokenServerkey自定义,调用judgeTokenIsEqual方法时的tokenClientkey一定要与前端页面的key一致。

以上这篇java token生成和校验的实例代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/571926.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用AsyncTask来获取网络图片

先看下运行结束 这里有两个Button 点击第一个Button运行的结果&#xff01;第一张有一个旋转的灰色圈圈&#xff01; 点击第二个Button运行的结果如下&#xff1a;带进度条的 ok,看下实现方法 先在配置清单中加一个访问网络的权限&#xff01; <uses-permission android:nam…

bilibili有电脑版吗_哪个手机便签软件有电脑版?有跨平台的桌面便签软件吗 - 学显...

如果仔细观察的话&#xff0c;你会发现&#xff1a;现在很多手机桌面上都有一款名叫“便签”的app小软件。其实&#xff0c;这是手机系统自带的一款备忘小工具&#xff0c;是为了方便用户记事而设计的。也就是说&#xff0c;平时如果有什么事儿需要记下来的话&#xff0c;就可以…

java 执行顺序混乱_java类执行顺序问题

经常遇到的面试题&#xff0c;一个类继承另一个类然后问输出的结果是什么。个人觉得就是考类的输出问题(亲测)第一&#xff1a;单一的类执行顺序package Test;public class person {static{System.out.println("父类的静态块");}person(){System.out.println("父…

win10关机后自动重启_安卓手机重启和关机后再开机,区别原来这么大!别不当回事...

现在大家用智能手机&#xff0c;只会在以下几种情况关机&#xff0c;一种是用到没电&#xff0c;自动关机了。另一种是手机有点卡顿&#xff0c;通过关机再开机的方式&#xff0c;释放RAM内存&#xff0c;提高手机运行速度。而现在的很多手机&#xff0c;比如小米手机&#xff…

java 遍历属性文件路径_Java项目中读取properties文件,以及六种获取路径的方法...

Java读取properties文件的方法比较多&#xff0c;网上最多的文章是"Java读取properties文件的六种方法"&#xff0c;但在Java应用中&#xff0c;最常用还是通过java.lang.Class类的getResourceAsStream(String name) 方法来实现&#xff0c;但我见到众多读取properti…

前端周报:前端面试题及答案总结;JavaScript参数传递的深入理解

1、2017前端面试题及答案总结 |掘金技术征文 "金三银四&#xff0c;金九银十"&#xff0c;用来形容求职最好的几个月。但是随着行业的饱和&#xff0c;初中级前端er就业形势不容乐观。 行业状态不可控&#xff0c;我们能做的当然只是让自己变得更加具有竞争力。 今年…

python二级考试真题_全国BIM技能等级考试真题全套(一/二级,全专业,28套)

BIM技能等级考试即将到来&#xff0c;你准备好了吗&#xff1f;今日为大家整理了一套网友上传的BIM等级考试全套真题&#xff0c;供大家学习参考~BIM一级真题解析课程限免&#xff1a;(点我)全国BIM技能等级考试真题解析(一级)仅限6月5日一天免费第一期全国BIM技能等级考试一级…

java frame清除控件_java – 清除JFrame的组件并添加新组件

我有一个JFrame,它有一些选项.当按下OK按钮时,我想要相同的JFrame清除内容并添加新内容.我试过了,但问题是新的JFrame被弹出.我究竟做错了什么&#xff1f;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.IOExcept…

Awk使用方法简介

AWK AWK简介&#xff1a;awk是一个强大的文本分析工具&#xff0c;相对于grep的查找&#xff0c;sed的编辑&#xff0c;awk在其对数据分析并生成报告时&#xff0c;显得尤为强大。简单来说awk就是把文件逐行的读入&#xff0c; 以空格为默认分隔符将每行切片…

矩形波如何傅立叶展开_金科文化会不会连续拉板?两位同学展开激辩

【编者按&#xff1a;金科文化是我们昨晚理论上留下的两道作业题之一&#xff0c;要求同学们根据课程内容&#xff0c;判断一下它是否符合连板青云的条件&#xff1f;后市如何预判&#xff1f;操作计划怎么制定&#xff1f;今天&#xff0c;很多同学就此展开了分析和讨论。今晚…

java web 不用框架_MyShop-不用框架的基础javaweb项目

javaweb基础开发Servletjspmysqlhtmlcssjs(找一个前端模板&#xff0c;一大堆html,自己写的没有模板的美观)数据库设计来一个最基础的用户表drop table ifexists myshop_user;create table myshop_user(USER_ID varchar(32) not null,USER_NAME varchar(20) not null,USER_PASS…

程序包管理器控制台 Add-Migration 用法

需要注意的是&#xff1a; 1.任何对数据库的操作都在代码和程序包管理控制台完成&#xff0c;千万不要自己去修改数据库&#xff0c;no&#xff01; 2.ef中创建数据库的表必须要有主键~&#xff01;否则 就不让你成功~ 现在来说如何映射 第一步创建在代码model中创建类 第二步 …

ipad如何连接电脑_电脑无法连接外网远程调试,一文教你如何用手机让台式机连接外网...

在弱电施工中&#xff0c;设备调试是一个很重要的环节&#xff0c;施工这么久就是为了实现弱电各系统的功能&#xff0c;调试是每一个弱电人系必需会的技能&#xff0c;也是检验你结合能力一种体现。在调试中会遇到各种你想不到的问题&#xff0c;当遇到问题时&#xff0c;你应…

java 多线程两种方式_JAVA多线程实现的两种方式

java多线程实现方式主要有两种&#xff1a;继承Thread类、实现Runnable接口1、继承Thread类实现多线程继承Thread类的方法尽管被我列为一种多线程实现方式&#xff0c;但Thread本质上也是实现了Runnable接口的一个实例&#xff0c;它代表一个线程的实例&#xff0c;并且&#x…

CAN总线学习资料

CAN总线呕心沥血教程 https://wenku.baidu.com/view/486647f47c1cfad6195fa794.html转载于:https://www.cnblogs.com/codecamel/p/7605480.html

安卓手机浏览器排行_安卓手机性能排行榜:国产手机集体“出位”,华为却在角落哭泣?...

华为手机的芯片一直都坚称是国产的骄傲&#xff0c;但是现在的华为芯片出现了一系列的问题&#xff0c;甚至有人预言在今年九月份之后&#xff0c;华为就不再会获得台积电的芯片供应了。这样&#xff0c;对华为来说无疑是不好的势头&#xff0c;而且芯片刚被市场认可&#xff0…

python os.access_os.access(path, mode)

os.access(path, mode)描述 (Description)方法access()使用真实的uid/gid来测试对路径的访问。 大多数操作都将使用有效的uid/gid&#xff0c;因此可以在suid/sgid环境中使用此例程来测试调用用户是否具有对path的指定访问权限。如果允许访问&#xff0c;则返回True&#xff0c…

HDnoip2017题解

那么&#xff0c;作为一名初入信息竞赛的选手&#xff0c;我也试着开始用博客记录自己的学习历程&#xff0c;那么这篇文章先简单介绍一下我自己吧。 本人开始学习信息学大概以来&#xff0c;主要都是用的C&#xff0c;所以对其他语言并不是十分熟悉。2016我还只是一名NOIP普及…

_Linux结束进程到底有多少种方法?

请关注本头条号&#xff0c;每天坚持更新原创干货技术文章。如需学习视频&#xff0c;请在微信搜索公众号“智传网优”直接开始自助视频学习。1. 前言我们经常在Linux里使用kill命令来结束某后台进程。但kill命令实际上是向进程发送信号&#xff0c;并且有多种信号。终止运行一…

svg mysql_SVG 实例

SVG 实例简单的 SVG 实例一个简单的SVG图形例子&#xff1a;这里是SVG文件(SVG文件的保存与SVG扩展)&#xff1a;/p>"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">stroke-width"2" fill"red" />SVG 代码解析&#xff1a;第一行…