JWT官网: https://jwt.io/
JWT(Java版)的github地址:https://github.com/jwtk/jjwt

JWT请求流程

  1. 用户使用账号和面发出post请求;
  2. 服务器使用私钥创建一个jwt;
  3. 服务器返回这个jwt给浏览器;
  4. 浏览器将该jwt串在请求头中像服务器发送请求;
  5. 服务器验证该jwt;
  6. 返回响应的资源给浏览器。

JWT的主要应用场景

  1. 前后端分离
  2. 单点登录(sso)
  3. 分布式微服务

一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。 信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。

优点

  1. 简洁(Compact): 可以通过URLPOST参数或者在HTTP header发送,因为数据量小,传输速度也很快
  2. 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
  3. 因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持。
  4. 不需要在服务端保存会话信息,特别适用于分布式微服务。
  5. JWT只通过算法实现对Token合法性的验证,不依赖数据库,Memcached的等存储系统,因此可以做到跨服务器验证,只要密钥和算法相同,不同服务器程序生成的Token可以互相验证。

JWT的token机制

JWT标准的token包含三部分:

  1. header(头部),头部信息主要包括(参数的类型--JWT,签名的算法--HS256)
  2. poyload(负荷),负荷基本就是自己想要存放的信息(因为信息会暴露,不应该在载荷里面加入任何敏感的数据),有两个形式,下边会讲到
  3. sign(签名),签名的作用就是为了防止恶意篡改数据

为什么要使用签名

签名解决了数据传输过程中参数被篡改的风险
一般而言,加密算法对于不同的输入产生的输出总是不一样的,如果有人对Header以及Payload的内容解码之后进行修改,再进行编码的话,那么新的头部和载荷的签名和之前的签名就将是不一样的。而且,如果不知道服务器加密的时候用的密钥的话,得出来的签名也一定会是不一样的。

服务器应用在接受到JWT后,会首先对头部和载荷的内容用同一算法再次签名。如果服务器应用对头部和载荷再次以同样方法签名之后发现,自己计算出来的签名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token

<!-- json web token  -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>package com.application.utils;import java.util.Calendar;
import java.util.Date;import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;public class TokenUtil {/*** 加密* @author Jason* @date 2019-03-29* @param id 用户id* @param username 用户名称* @param password 用户密码* @param deviceId 设备号* @param formatDate 过期日期* @return 加密的token*/public static String createToken(String id, String username, String password, String deviceId, String formatDate) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;long nowMillis = Calendar.getInstance().getTimeInMillis();Date now = new Date(nowMillis);// 加密秘钥byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("123456789");SecretKeySpec signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());JwtBuilder builder = Jwts.builder().setIssuedAt(now).setId(id).setIssuer(username).setSubject(password).setAudience(deviceId).signWith(signatureAlgorithm,signingKey);// 设置过期日期Date expirationDate = null;if (null != formatDate) {try {expirationDate = DateUtil.stringToDate(formatDate);} catch (Exception e) {expirationDate = getDefultExpirationDate();}if(null == expirationDate || expirationDate.before(new Date())){expirationDate = getDefultExpirationDate();}} else {expirationDate = getDefultExpirationDate();}builder.setExpiration(expirationDate);return builder.compact();}/*** 获取默认的过期时间,默认是七天以后* @author Arwen Liu* @date 2018-10-29* @return Date*/private static Date getDefultExpirationDate(){long timeInMillis = Calendar.getInstance().getTimeInMillis();Long time = 1 * 1000 * 60 * 60 * 24 * 7l;time += timeInMillis;return new Date(time);}/*** 解密* @author Arwen Liu* @date 2018-10-29* @param token* @return Claims*/public static Claims parseToken(String token) {Claims claims = Jwts.parser()// s解密密钥,需要和 加密秘钥一致.setSigningKey(DatatypeConverter.parseBase64Binary("123456789")).parseClaimsJws(token).getBody();return claims;}public static void main(String[] args) {String secretToken = createToken("1001", "staff", "123456","deviceId", "2018-12-28");System.out.println("加密后---->" + secretToken);// ss解密Claims claims = parseToken(secretToken);System.out.println("解密后---->");System.out.println("id: " + claims.getId());System.out.println("username: " + claims.getIssuer());System.out.println("password: " + claims.getSubject());System.out.println("deviceId: "+ claims.getAudience());System.out.println("expiration: " + DateUtil.dateToString(claims.getExpiration(), "yyyy-MM-dd"));}}

验证token的策略

  1. 让客户端保存到 localStorage 每次请求带着token
  2. 放到cookie里面 然后定义一个拦截器 每次都从cookie里面查询并验证token
  3. 放到header里面 和 cookie类似

在退出登录时怎样实现JWT Token失效呢?
退出登录, 只要客户端端把Token丢弃就可以了,服务器端不需要废弃Token。

怎样保持客户端长时间保持登录状态?

服务器端提供刷新Token的接口, 客户端负责按一定的逻辑刷新服务器Token。

服务器端是否应该从JWT中取出userid用于业务查询?

REST API是无状态的,意味着服务器端每次请求都是独立的,即不依赖以前请求的结果,因此也不应该依赖JWT token做业务查询, 应该在请求报文中单独加个userid 字段。
为了做用户水平越权的检查,可以在业务层判断传入的userid和从JWT token中解析出的userid是否一致, 有些业务可能会允许查不同用户的数据。

如何防范Replay Attacks

重复攻击

所谓重复攻击就是攻击者发送一个后端服务器已接收过的包,来达到攻击系统的目的。

比如在浏览器端通过用户名/密码验证获得签名的Token被木马窃取。即使用户登出了系统,黑客还是可以利用窃取的Token模拟正常请求,而服务器端对此完全不知道,因为JWT机制是无状态的。

可以在Payload里增加时间戳并且前后端都参与来解决:

1.前端生成token时,在payload里增加当前时间戳
2.后端接收后,对解析出来的时间戳和当前时间进行判断,
3.如果相差特定时间内(比如2秒),允许请求否则判定为重复攻击

参考 https://www.jianshu.com/p/e88d3f8151db

https://www.jianshu.com/p/836df92c06eb

https://blog.csdn.net/why15732625998/article/details/78534711

https://www.jianshu.com/p/e88d3f8151db

http://www.cnblogs.com/xiekeli/p/5607107.html

利用JWT安全验证(前后端分离,单点登录,分布式微服务)相关推荐

  1. 前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式

    演示Demo站点 http://sso.exrick.cn 开源版Github地址 https://github.com/Exrick/x-boot) 开发文档 https://www.kanclou ...

  2. JWT(解决前后端分离和微服务的用户会话跟踪问题)

    这里写目录标题 JWT:解决前后端分离和微服务的用户会话跟踪问题 与传统sessio验证的区别: 基于 token 的鉴权机制 JWT的主要引用场景及优点 JWT的构成: JWT搭建 案例: JWT: ...

  3. Django前后端分离实现登录验证码功能

    Django前后端分离实现登录验证码功能 当下最流行最热门的开发方式当属前后端分离开发,分工也更加明确与专注,前端也是越来越难,几天不学习就跟不上节奏,一个月不学习可以好不夸张的说,你已经不适合这个行 ...

  4. Android+SpringBoot前后端分离实现登录注册

    Android+SpringBoot前后端分离实现登录注册 一.登录 1.界面设计 2.Android端 (1)布局文件(activity_login) (2)java文件(LoginActivity ...

  5. 开发SpringBoot+Jwt+Vue的前后端分离后台管理系统VueAdmin - 前端笔记

    1. 前言 而接下来,我们即将开发一个前后端分离的后台管理系统VueAdmin.权限框架采用spring security,然后相对来说权限模块开发就多点代码,也仅此而已了.对了前端的系统界面也是我们 ...

  6. Spring Boot与JWT整合实现前后端分离的用户认证

    前言 本篇使用java-jwt作为JWT库,与Spring Boot整合实现前后端分离架构中用户认证. Spring Boot项目搭建参考: [Spring Boot系列]1. 项目搭建之一 关于JW ...

  7. CAS单点登出,调整CAS源码,实现前后端分离单点登出、清除redis、shiro登录状态

    前端点击"登出"按钮,跳转到CAS的登出. CAS默认配置了单点登出,在登出后,会向所有客户端系统发送这个用户登出的报文. 各客户端系统有责任接收并处理这个用户登出的报文,然后在注 ...

  8. Java前后端分离第三方登录_网站前后端分离情况下如何实现QQ微信等第三方登陆-Fun言...

    前言 最近在弄第三方登录,实现起来很简单,就是调几个接口获取个人信息即可,详细了解:maven项目整合QQauth2.0第三方登录详细说明,然后因为本网站是前后端分离的,所以不能再回调接口那里直接跳转 ...

  9. node+vue前后端分离实现登录时使用图片验证码

    记录一下前端使用验证码登录的过程 后端用的是node.js,关键模块是svg-captcha 前端使用的是vue2 最后的登录界面如下: 后端代码 先上代码,然后解释 const svgCaptcha ...

  10. 微信公众号前后端分离授权登录

    前后端分离模式下微信授权登录 https://blog.csdn.net/qq_39524670/article/details/81118721?utm_medium=distribute.pc_r ...

最新文章

  1. PHP多图片上传 并检查 加水印 源码
  2. RAC对单实例DG redo大小日志修改
  3. 【Linux】27_网站服务静态站点
  4. linux网络编程之Listen函数参数介绍
  5. matlab中count是干什么,matlab编程潮流计算的count值与什么有?
  6. 中国水下照明行业市场供需与战略研究报告
  7. org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘medicinesId
  8. Lambert 投影转换相关代码
  9. win7下虚拟显示器完成记(virtual monitor)——VDI显卡透传场景
  10. “差不多先生”姚劲波和不再神奇的58同城
  11. webrtc学习--websocket服务器(二) (web端播放h264)
  12. 随机森林python反欺诈_携程金融自动化迭代反欺诈模型体系
  13. 大话西游2玩家最多的服务器,大话西游2最火爆的服务器凌烟阁,玩家一次预约成功...
  14. Ubuntu 搭建强大的 IDE —— Vim + Vundle + 插件
  15. Notes Fifteenth Day-渗透攻击-红队-内部信息搜集
  16. c mysql加密解密_mysql内置加密函数对数据加密
  17. 毕业答辩PPT模板(10套免费+精选)
  18. 手动 php-mysql_win7下手动配置apache+php+mysql记
  19. 一个人的格局,往往决定着一生【看世间繁华,品百味人生】
  20. 当前支付有效提高线下支付场景效率?

热门文章

  1. 开源GIS浅谈 【转】
  2. 七日年化收益率怎么算「知识普及」
  3. 剑指Offer——求1+2+3+...+n
  4. 什么是DBMS,DB,DBMS?
  5. python解题时间_1小时还是30秒?Python给你的另一种数据处理选择
  6. 模仿人类逻辑,首个BERT模型AI通过初二科学考试!研究人员:完成了老板遗愿...
  7. 紧急!!!请尽快将Flash Player升级到9.0.124
  8. crc生成多项式java_CRC 生成多项式
  9. vivo联手京东,打通线上线下营销生态
  10. Hadoop3.x版本安装及其应用部署