利用JWT安全验证(前后端分离,单点登录,分布式微服务)
JWT官网: https://jwt.io/
JWT(Java版)的github地址:https://github.com/jwtk/jjwt
JWT请求流程
- 用户使用账号和面发出post请求;
- 服务器使用私钥创建一个jwt;
- 服务器返回这个jwt给浏览器;
- 浏览器将该jwt串在请求头中像服务器发送请求;
- 服务器验证该jwt;
- 返回响应的资源给浏览器。
JWT的主要应用场景
- 前后端分离
- 单点登录(sso)
- 分布式微服务
一旦用户完成了登陆,在接下来的每个请求中包含JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。 信息交换在通信的双方之间使用JWT对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。
优点
- 简洁(Compact): 可以通过
URL
,POST
参数或者在HTTP header
发送,因为数据量小,传输速度也很快 - 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
- 因为
Token
是以JSON
加密的形式保存在客户端的,所以JWT
是跨语言的,原则上任何web形式都支持。 - 不需要在服务端保存会话信息,特别适用于分布式微服务。
- JWT只通过算法实现对Token合法性的验证,不依赖数据库,Memcached的等存储系统,因此可以做到跨服务器验证,只要密钥和算法相同,不同服务器程序生成的Token可以互相验证。
JWT的token机制
JWT标准的token包含三部分:
- header(头部),头部信息主要包括(参数的类型--JWT,签名的算法--HS256)
- poyload(负荷),负荷基本就是自己想要存放的信息(因为信息会暴露,不应该在载荷里面加入任何敏感的数据),有两个形式,下边会讲到
- 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的策略
- 让客户端保存到 localStorage 每次请求带着token
- 放到cookie里面 然后定义一个拦截器 每次都从cookie里面查询并验证token
- 放到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安全验证(前后端分离,单点登录,分布式微服务)相关推荐
- 前后端分离单点登录SSO实现方案 淘宝、京东跨域获取Cookie、OAuth2、QQ客户端多种模式
演示Demo站点 http://sso.exrick.cn 开源版Github地址 https://github.com/Exrick/x-boot) 开发文档 https://www.kanclou ...
- JWT(解决前后端分离和微服务的用户会话跟踪问题)
这里写目录标题 JWT:解决前后端分离和微服务的用户会话跟踪问题 与传统sessio验证的区别: 基于 token 的鉴权机制 JWT的主要引用场景及优点 JWT的构成: JWT搭建 案例: JWT: ...
- Django前后端分离实现登录验证码功能
Django前后端分离实现登录验证码功能 当下最流行最热门的开发方式当属前后端分离开发,分工也更加明确与专注,前端也是越来越难,几天不学习就跟不上节奏,一个月不学习可以好不夸张的说,你已经不适合这个行 ...
- Android+SpringBoot前后端分离实现登录注册
Android+SpringBoot前后端分离实现登录注册 一.登录 1.界面设计 2.Android端 (1)布局文件(activity_login) (2)java文件(LoginActivity ...
- 开发SpringBoot+Jwt+Vue的前后端分离后台管理系统VueAdmin - 前端笔记
1. 前言 而接下来,我们即将开发一个前后端分离的后台管理系统VueAdmin.权限框架采用spring security,然后相对来说权限模块开发就多点代码,也仅此而已了.对了前端的系统界面也是我们 ...
- Spring Boot与JWT整合实现前后端分离的用户认证
前言 本篇使用java-jwt作为JWT库,与Spring Boot整合实现前后端分离架构中用户认证. Spring Boot项目搭建参考: [Spring Boot系列]1. 项目搭建之一 关于JW ...
- CAS单点登出,调整CAS源码,实现前后端分离单点登出、清除redis、shiro登录状态
前端点击"登出"按钮,跳转到CAS的登出. CAS默认配置了单点登出,在登出后,会向所有客户端系统发送这个用户登出的报文. 各客户端系统有责任接收并处理这个用户登出的报文,然后在注 ...
- Java前后端分离第三方登录_网站前后端分离情况下如何实现QQ微信等第三方登陆-Fun言...
前言 最近在弄第三方登录,实现起来很简单,就是调几个接口获取个人信息即可,详细了解:maven项目整合QQauth2.0第三方登录详细说明,然后因为本网站是前后端分离的,所以不能再回调接口那里直接跳转 ...
- node+vue前后端分离实现登录时使用图片验证码
记录一下前端使用验证码登录的过程 后端用的是node.js,关键模块是svg-captcha 前端使用的是vue2 最后的登录界面如下: 后端代码 先上代码,然后解释 const svgCaptcha ...
- 微信公众号前后端分离授权登录
前后端分离模式下微信授权登录 https://blog.csdn.net/qq_39524670/article/details/81118721?utm_medium=distribute.pc_r ...
最新文章
- PHP多图片上传 并检查 加水印 源码
- RAC对单实例DG redo大小日志修改
- 【Linux】27_网站服务静态站点
- linux网络编程之Listen函数参数介绍
- matlab中count是干什么,matlab编程潮流计算的count值与什么有?
- 中国水下照明行业市场供需与战略研究报告
- org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘medicinesId
- Lambert 投影转换相关代码
- win7下虚拟显示器完成记(virtual monitor)——VDI显卡透传场景
- “差不多先生”姚劲波和不再神奇的58同城
- webrtc学习--websocket服务器(二) (web端播放h264)
- 随机森林python反欺诈_携程金融自动化迭代反欺诈模型体系
- 大话西游2玩家最多的服务器,大话西游2最火爆的服务器凌烟阁,玩家一次预约成功...
- Ubuntu 搭建强大的 IDE —— Vim + Vundle + 插件
- Notes Fifteenth Day-渗透攻击-红队-内部信息搜集
- c mysql加密解密_mysql内置加密函数对数据加密
- 毕业答辩PPT模板(10套免费+精选)
- 手动 php-mysql_win7下手动配置apache+php+mysql记
- 一个人的格局,往往决定着一生【看世间繁华,品百味人生】
- 当前支付有效提高线下支付场景效率?
热门文章
- 开源GIS浅谈 【转】
- 七日年化收益率怎么算「知识普及」
- 剑指Offer——求1+2+3+...+n
- 什么是DBMS,DB,DBMS?
- python解题时间_1小时还是30秒?Python给你的另一种数据处理选择
- 模仿人类逻辑,首个BERT模型AI通过初二科学考试!研究人员:完成了老板遗愿...
- 紧急!!!请尽快将Flash Player升级到9.0.124
- crc生成多项式java_CRC 生成多项式
- vivo联手京东,打通线上线下营销生态
- Hadoop3.x版本安装及其应用部署