点击上方 好好学java ,选择 星标 公众号

重磅资讯、干货,第一时间送达

今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招!

 个人原创100W+访问量博客:点击前往,查看更多
作者:巨人大哥
来源:cnblogs.com/jurendage/p/9219041.html

目的:Java开源生鲜电商平台-Java后端生成Token目的是为了用于校验客户端,防止重复提交.

技术选型:用开源的JWT架构。

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  *  */
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一致。

Token主要是用于以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上密匙。

package com.franz.websocket;import com.franz.common.utils.StringUtils;
import com.franz.weixin.p3.oauth2.util.MD5Util;
import io.jsonwebtoken.*;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.jeecgframework.core.common.service.CommonService;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.DatatypeConverter;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;/*** OAuthTokenUtils* Token管理* @author nizhigengvip@163.com*/
public class OAuthTokenManager {private String APP_ID = "";private String APP_SECRET = "";private String KEY_SING =  ""; //用於存放TOKEN的標誌,Redisprivate LinkedHashMap<string, object=""> pairs = new LinkedHashMap();//封装json的mapprivate CommonService service;public static final int MINUTE_TTL = 60*1000;  //millisecondpublic static final int HOURS_TTL = 60*60*1000;  //millisecondpublic static final int DAY_TTL = 12*60*60*1000;  //millisecondprivate OAuthTokenManager() {}private static OAuthTokenManager single=null;public static OAuthTokenManager getInstance() {if (single == null) {single = new OAuthTokenManager();}return single;}public String getKEY_SING() {return KEY_SING;}public void setPairs(LinkedHashMap<string, object=""> pairs) {this.pairs = pairs;}public LinkedHashMap<string, object=""> getPairs() {return pairs;}public void put(String key, Object value){//向json中添加属性,在js中访问,请调用data.map.keypairs.put(key, value);}public void remove(String key){pairs.remove(key);}/*** 總體封裝* @param appid* @param secret* @param logicInterface 回調函數* @return*/public String token(String appid,String secret,LogicInterface logicInterface){//获取appid和secretthis.accessPairs(appid,secret);//验证appid和secretS,获取对象载体Object subject = this.loginAuthentication(logicInterface);//生成JWT签名数据ToKenString token = this.createToken(this.generalSubject(subject),this.MINUTE_TTL);return token;}public void accessPairs(String APP_ID, String APP_SECRET) {this.APP_ID = APP_ID;this.APP_SECRET = APP_SECRET;//this.KEY_SING = MD5Util.MD5Encode(APP_ID+"_"+APP_SECRET, "UTF-8").toUpperCase();//要用到的时候才用}public Object loginAuthentication(LogicInterface logicInterface){if (StringUtils.isNotBlank(APP_ID) && StringUtils.isNotBlank(APP_SECRET)) {Map<string, object=""> map = new HashMap<>();map.put("APP_ID",APP_ID);map.put("APP_SECRET",APP_SECRET);if(logicInterface == null || logicInterface.handler(map) == null){return map;}else {return logicInterface.handler(map);}} else {return null;}}/*** 由字符串生成加密key* @return*/public SecretKey generalKey(){String stringKey = APP_ID+APP_SECRET;byte[] encodedKey = Base64.decodeBase64(stringKey);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 生成subject信息* @param obj* @return*/public static String generalSubject(Object obj){if(obj != null ) {JSONObject json = JSONObject.fromObject(obj);return json.toString();}else{return "{}";}}/*** 创建token* @param subject* @param ttlMillis* @return* @throws Exception*/public String createToken(String subject, long ttlMillis) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis);SecretKey key = generalKey();JwtBuilder builder = Jwts.builder().setId(APP_ID).setIssuedAt(now).setSubject(subject).signWith(signatureAlgorithm, key);if (ttlMillis >= 0) {long expMillis = nowMillis + ttlMillis;Date exp = new Date(expMillis);builder.setExpiration(exp);}return builder.compact();}/*** 解密token* @param token* @return* @throws Exception*/public Claims validateToken(String token) throws Exception{Claims claims = Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();/*System.out.println("ID: " + claims.getId());System.out.println("Subject: " + claims.getSubject());System.out.println("Issuer: " + claims.getIssuer());System.out.println("Expiration: " + claims.getExpiration());*/return claims;}
}
import com.ewider.weixin.p3.oauth2.util.MD5Util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;/*** OAuthTokenController** @author Franz.ge.倪志耿*/
@Scope("prototype")
@Controller
@RequestMapping("/oAuthToken")
public class OAuthToken {/*** 獲取Token* @param grant_type* @param appid* @param secret* @return*/@RequestMapping(params = "token",method = RequestMethod.GET)@ResponseBodypublic Object token (@RequestParam(value = "grant_type") String grant_type, @RequestParam(value = "appid") String appid,@RequestParam(value = "secret") String secret,HttpServletResponse response) {Map<string, object=""> map = new HashMap<>();switch (grant_type) {case "authorization_code" : //授权码模式(即先登录获取code,再获取token)break;case "password" : //密码模式(将用户名,密码传过去,直接获取token)break;case "client_credentials" : //客户端模式(无用户,用户向客户端注册,然后客户端以自己的名义向’服务端’获取资源)OAuthTokenManager oAuthTokenManager = OAuthTokenManager.getInstance();String token = oAuthTokenManager.token(appid, secret,null);//loginInterface是业务逻辑回掉函数//返回Tokenmap.put("access_token",token);map.put("expires_in",OAuthTokenManager.MINUTE_TTL/1000);break;case "implicit" : //简化模式(在redirect_uri 的Hash传递token; Auth客户端运行在浏览器中,如JS,Flash)break;case "refresh_token" : //刷新access_tokenbreak;}return map;}@RequestMapping(params = "loginAuth2",method = RequestMethod.GET)@ResponseBodypublic Object loginAuth2 (HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "accessToken") String accessToken ){Map<string, object=""> map = new HashMap<>();//COOKIE不存在:解析验证正确性try {OAuthTokenManager oAuthTokenManager = OAuthTokenManager.getInstance();Claims claims = oAuthTokenManager.validateToken(accessToken);if (claims != null ) {map.put("state","success");map.put("loginAuth","采用Token登录");int validMillis = (int)(claims.getExpiration().getTime()-System.currentTimeMillis());if(validMillis > 0) {//交給容器管理,可以存放redis,這裡模擬是cookieCookie cookie = new Cookie(MD5Util.MD5Encode("MD5SING", "UTF-8").toUpperCase(), accessToken);cookie.setMaxAge(validMillis/1000);response.addCookie(cookie);}}else{map.put("state","fail");}}catch (MalformedJwtException | SignatureException e){map.put("state","signature");//改造簽名,或者無效的Tokenmap.put("loginAuth","該Token無效");//改造簽名,或者無效的Token}catch (ExpiredJwtException e){map.put("state","expired");//改造簽名,或者無效的Tokenmap.put("loginAuth","Token已經過時");}catch (Exception e) {e.printStackTrace();map.put("state","fail");}return map;}@RequestMapping(params = "index",method = RequestMethod.GET)@ResponseBodypublic Object index (HttpServletRequest request, HttpServletResponse response){Map<string, object=""> map = new HashMap<>();//从COOKIE中查找,模拟访问,可以集成容器管理Cookie[] cookies = request.getCookies();if (cookies!=null) {for (int i = cookies.length-1; i >= 0; i--) {Cookie cookie = cookies[i];if (cookie.getName().equals(MD5Util.MD5Encode("MD5SING", "UTF-8").toUpperCase())) {//跳过登陆map.put("index","采用Redis登录");return map;}}}map.put("index","你的Token已经销毁");return map;}}
<dependency><groupid>io.jsonwebtoken</groupid><artifactid>jjwt</artifactid><version>0.7.0</version>
</dependency>

推荐文章

  • 硬刚一周,3W字总结,一年的经验告诉你如何准备校招!

  • 今年的校招,Java 好拿 offer 吗?

  • 10月了,该聊聊今年秋招了!

  • 聊聊在腾讯实习快一个月的感受

原创电子书历时整整一年总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及校招的总结,各种高频面试题已经全部进行总结,按照章节复习即可,已经拿到了大厂offer。
原创思维导图扫码或者微信搜 程序员的技术圈子 回复 面试 领取原创电子书和思维导图。

AWT架构生成与设计Token相关推荐

  1. Java生鲜电商平台-App系统架构开发与设计

    Java生鲜电商平台-App系统架构开发与设计 说明:阅读此文,你可以学习到以下的技术分享 1.Java生鲜电商平台-App架构设计经验谈:接口的设计 2.Java生鲜电商平台-App架构设计经验谈: ...

  2. 认证鉴权与API权限控制在微服务架构中的设计与实现

    引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现. 1. 背景 最近在做权限相关服务的开发, ...

  3. (三)系统与架构级低功耗设计

    前面讲解了使用EDA工具(主要是power compiler)进行功耗分析的流程,这里我们将介绍在数字IC中进行低功耗设计的方法,同时也结合EDA工具(主要是Design Compiler)如何实现. ...

  4. 认证鉴权与API权限控制在微服务架构中的设计与实现(一)

    作者: [Aoho's Blog] 引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的第一篇,本系列预计四篇文章讲解微服务下的认证鉴权与API权限控制的实现. 1. ...

  5. 系统架构设计师 - 软件架构设计 - 基于架构开发方法 ABSD (Architecture-Based Soft Design)

    文章目录 基于架构的开发方法 体系结构需求 体系结构设计 体系结构文档化 体系结构复审 体系结构实现 体系结构演化 语义上的 "体系结构" = "架构" 基于架 ...

  6. 一个C/S结构的优秀例子: 延迟补偿在C/S架构游戏协议设计和优化中的应用

    这篇文章介绍了cs这样的第一人称射击游戏中如何实现延迟补偿.非第一人称设计游戏设计也可以参考其中一些思想 原文地址: https://developer.valvesoftware.com/wiki/ ...

  7. Spring Cloud与微服务学习总结(6)——认证鉴权与API权限控制在微服务架构中的设计与实现(四)

    本文转载自(http://blueskykong.com/2017/10/26/security4/) 1. 前文回顾 首先还是照例对前文进行回顾.在第一篇 认证鉴权与API权限控制在微服务架构中的设 ...

  8. Spring Cloud与微服务学习总结(5)——认证鉴权与API权限控制在微服务架构中的设计与实现(三)

    本文转载自( http://blueskykong.com/2017/10/24/security3/) 1. 前文回顾 在开始讲解这一篇文章之前,先对之前两篇文章进行回忆下.在第一篇 认证鉴权与AP ...

  9. Spring Cloud与微服务学习总结(4)——认证鉴权与API权限控制在微服务架构中的设计与实现(二)

    本文转载自(http://blueskykong.com/2017/10/19/security2/) 1. 系统概览 在上一篇 认证鉴权与API权限控制在微服务架构中的设计与实现(一)介绍了该项目的 ...

最新文章

  1. 清华首超新加坡国立大学,成亚洲第一;苏州大学成211学科黑马丨US News 2021
  2. python爬虫入门教程-Python 爬虫介绍
  3. CMU Facebook论文解读 | 非局部神经网络(附代码实现)
  4. python 设置输入法为英文,appium+python环境下的输入法切换
  5. C++set容器去重法
  6. 谢烟客---------Linux之DNS服务系统的基础知识
  7. Dubbo-go v3.0 正式发布 ——打造国内一流开源 Go 服务框架
  8. RDD Join 性能调优
  9. vscode 找不到path路径
  10. 8000401a错误解决方式(Excel)
  11. 边走边拍───南极三岛之行
  12. Linux 网卡配置eth1修改为eth0
  13. 在使用html5的video标签播放视频时为何只有声音却没有图像
  14. 我们都希望有一部属于自己的电脑。
  15. BUUCTF MD5
  16. 卖保健产品怎么引流?关于做男性保健品怎么引流的详细介绍
  17. Android Mms专题之:Mms概览介绍
  18. NLP04-pyLDAvis可视化主题
  19. python3模拟IP进行刷投票
  20. [转]杜比TrueHD(Dolby TrueHD)音频编码解析

热门文章

  1. sql server日期时间函数
  2. 利用COM+对数据库操作进行单元测试
  3. getaddrinfo函数
  4. ON_MESSAGE,ON_COMMAND和ON_NOTIFY的区别和联系
  5. 计算机文档插入操作,电脑在word2007文档中插入数学公式的方法
  6. Hyperledger Fabric 私有数据(1)概念
  7. HMAC(1)消息认证码MAC算法
  8. 【Flask项目2】多进程下的日志文件(2)
  9. 2022-02-09
  10. [Zer0pts2020]ROR