问题原因

在传统的项目中我们利用,session+cookie来保持用户的登录状态,但这在前后端分离项⽬目中出现了问题;sessionid是使用cookie存储在客户端的,而cookie遵守同源策略,只在同源的请求中有效,这就导致了问题出现:前后端分离后静态资源完全可能(而且经常…)部署到另一个域下,导致cookie失效。

虽然我们可以在cookie中指定domain来解决,但是cookie必须针对性的设置作用域,这对于有多个不同域要共享cookie时,可操作性差,难以维护。

1、上述问题出现在前后端分离的web项目中,对于前后端分离的原生CS结构项目而言,很多客户端默认是不处理session和cookie的,需要进行相应的设置2、在分布式或集群的项目中,共享session和cookie也是一大问题,必须引入第三方来完成session的 存储和共享(也可通过中间层做cookie转发如Nginx.Node.js),这也是传统单体服务无法支持分布式和集群的问题所在

正因为有这些问题,导致session+cookie的方式在某些项目中使用起来变得很麻烦,这时候就需要⼀一种新的状态维持的方式;

JWT

JWT全称(json WEB token),是基于json数据结构的数据验证⽅方式,其本质是对json数据进⾏行行加密后产⽣生的 字符串串

JWT的亮点:

 安全 稳定易用 ⽀支持 JSON

原理:

之所以使用session和cookie是因为HTTP的无状态性质,导致服务器无法识别多次请求是否来自同 一个用户

JWT可以对用户信息进行加密生成一个字符串,下发到客户端,客户端在后续请求中携带该字符串,服务器解析后取出用户信息,从而完成用户身份的识别,如下图:

JWT的数据结构

三个组成部分如下:

 Header(头部)Payload(负载)Signature(签名)

Header

Header 部分是一个 JSON 对象,描述 JWT 的元数据,例如签名算法等,像下面这样:

 {"alg": "HS256","typ": "JWT"}
alg属性表示签名的算法,默认是 HMAC SHA256;typ属性表示这个令牌(token)的类型统一写为JWT

最后使用base64URL算法转换为字符串;

Payload

Payload 部分也是一个 JSON 对象,用来存放真正需要传递的数据,JWT 规定了7个保留字段,如下:

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

服务器如果需要在Payload中添加用于识别用户身份的数据,也是键值对形式,注意不可使用保留字段,像下面这样:

{"sub": "test JWT","name": "lbb","isadmin": true
}

Payload同样使用base64URL算法转换为字符串;

强调:

Payload数据默是不加密的,攻击者可以通过相同的方式解析获取,若要将用户的关键数据放入其中则必须对其进行额外的加密

Signature
部分是对前两部分的签名,防止数据篡改。

签名时需要指定一个密钥(secret)。密钥只有服务器才知道,不能泄露给用户。然后使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的方式产生签名:

signature = HMACSHA256(base64UrlEncode(header) + "." +  base64UrlEncode(payload),  secret)

最后把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点".分隔返回给用户,如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiJ0ZXN0IEpXVCIsImV4cCI6MTU4NjMyMzcxNCwidXNlcklkIjoic3dxMTMyZCJ9.
my8x7N5hIYZndAAUqL-wyeNY1dPU0rsNwDw_5xFsjAA

JWT是一个很长的字符串,分为成三个部分,中间用点.隔开
注意: JWT 内部是没有换行的,这里只是为了便于展示,将它写成了几行。

总结:

优点

 满足REST Full的无状态要求(为了提高系统的扩展性,REST要求所有信息由请求端来提供,如此才使得JWT成为了分布式,集群构架的首选方式)在分布式,集群系统中使身份验证变得非常简单可用于其他数据交换合理的使用可减少数据库查询次数

缺点

 对于同样的数据JWT整体大小超过同样数据的cookie,这会增加网络负担服务器每次解析JWT都需要再次执行对应的算法,这将增加系统负担在传统单体服务,和WEBApp形式的前后端分离项目中使用JWT反而不如Session+cookie

注意事项:

     JWT的payload部分是不加密的,如果要放入关键数据则必须对其进行加密,或是将最后的JWT整体加密JWT本身用于认证,一旦泄露,则任何人都可以使用该令牌,获得其包含的所有权限,为了提高安全性.JWT的有效期不应太长,对于一些非常权限,建议在请求时再次验证

JWT的使用

使用JWT的步骤总体分为三步

 1、生成JWT2、验证JWT3、提取数据

案例:

所用的包:

生成JWT:

@WebServlet(name = "TokenServlet",urlPatterns = "/token")
public class TokenServlet extends HttpServlet {public static final String key = "QWDWQD456GTRHRHTGRRH232KYUVBZSRG";protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取参数String name = request.getParameter("name");String pwd = request.getParameter("pwd");//登录if ("lbb".equals(name) && "123456".equals(pwd)){//登陆成功JWTCreator.Builder builder = JWT.create();Algorithm algorithm = Algorithm.HMAC256(key);//支持链式调用String token = builder.withSubject("test JWT") //设置主题.withExpiresAt(new Date(new Date().getTime() + (1000 * 60 * 30)))//过期时间.withClaim("userId", "swq132d") //负载数据(自定义).sign(algorithm);//签名,产生JWT,参数是算法//token放入响应头response.setHeader("token",token);response.getWriter().println("{\"succ\":ture}");}else {//登陆失败response.getWriter().println("{\"succ\":false}");}}
}

测试:


验证JWT及提取数据:

@WebServlet(name = "CheckServlet", urlPatterns = "/check")
public class CheckServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//取出tokenString token = request.getHeader("token");if (token != null) {//token有//验证token即是否过期或被篡改Algorithm algorithm = Algorithm.HMAC256(TokenServlet.key);JWTVerifier verifier = JWT.require(algorithm).build();try {verifier.verify(token);//验证成功,提取数据DecodedJWT decode = JWT.decode(token);String userId = decode.getClaim("userId").asString();//响应参数JSONObject param = new JSONObject();param.put("succ",true);param.put("userId",userId);response.getWriter().println(JSON.toJSONString(param));} catch (JWTDecodeException e) {//token失效或被篡改JSONObject param = new JSONObject();param.put("succ",false);param.put("err","失效或被篡改");response.getWriter().println(JSON.toJSONString(param));}} else {//没有tokenJSONObject param = new JSONObject();param.put("succ",false);param.put("err","没有token");response.getWriter().println(JSON.toJSONString(param));}}
}

测试:

前后端分离状态保持问题之JWT相关推荐

  1. 【Gorho】springboot整合Shiro+jwt 前后端分离 超级详细的shiro+jwt鉴权过程

    shiro+jwt+springboot 说在前面 简介 项目环境(pom.xml) 项目结构(各种包和类) 鉴权流程 具体代码 配置Shiro 配置JWTUtils 定义JwtFilter 定义Jw ...

  2. 【Vue+SpringBoot】超详细!一周开发一个SpringBoot + Vue+MybatisPlus+Shiro+JWT+Redis前后端分离个人博客项目!!!【项目完结】

    项目目录 资源准备 前后端分离项目 技术栈 Java后端接口开发 1.前言 2.新建Springboot项目 3.整合mybatis plus 3.统一结果封装 4.整合shiro+jwt,并会话共享 ...

  3. 基于SpringBoot+Vue开发的前后端分离博客项目-Java后端接口开发

    文章目录 1. 前言 2. 新建Springboot项目 3. 整合mybatis plus 第一步:导依赖 第二步:写配置文件 第三步:mapper扫描+分页插件 第四步:代码生成配置 第五步:执行 ...

  4. SpringBoot+vue前后端分离博客项目

    SpringBoot+vue前后端分离博客项目 Java后端接口开发 1.前言 2.新建Springboot项目 3.整合mybatis plus 第一步:导入jar包 第二步:然后去写配置文件: 第 ...

  5. 超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!

    小Hub领读: 前后端分离的博客项目终于出来啦,真是花了好多心思录制咧.文末直接进入B站看视频哈! 作者:吕一明 项目代码:https://github.com/MarkerHub/vueblog 项 ...

  6. B站云E办Vue+SpringBoot前后端分离项目——MVC三层架构搭建后台项目

    本项目来源B站云E办,笔记整理了项目搭建的过程和涉及的知识点.对于学习来说,不是复制粘贴代码即可,要知其然知其所以然.希望我的笔记能为大家提供思路,也欢迎各位伙伴的指正. 项目前端学习笔记目录 B站云 ...

  7. 前后端分离架构下CSRF防御机制

    背景 1.什么是CSRF攻击? 这里不再介绍CSRF,已经了解CSRF原理的同学可以直接跳到:"3.前后端分离下有何不同?". 不太了解的同学可以看这两篇对CSRF介绍比较详细的参 ...

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

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

  9. SpringBoot+SpringSecurity前后端分离+Jwt的权限认证(改造记录)

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/zzzgd_666/article/details/96444829 前言 一般来说,我们用Spr ...

最新文章

  1. 停止对互联网的意淫吧,它不过是个信息技术啊
  2. python 中的 and / or
  3. 【展开讲讲?xmind日常小知识】xmind2020插入表格
  4. 《三基色组成方式》转
  5. 使用Ehcache+Redis实现分布式缓存
  6. 谈及未来的 AI, 也许你已身处其中 —— 记 InfoQ 对青云QingCloud 联合创始人林源的采访...
  7. 2016蓝桥杯省赛---java---B---6(方格填数)
  8. 免费实时汇率查询接口
  9. Java取交集方法retainAll()
  10. 基于Python爬取天眼查网站的企业信息
  11. 论文图片排版 Adobe Illustrator 操作演示
  12. 八、JDBC批量处理sql语句
  13. 想让你看的评论:我还是很喜欢你
  14. wingdings字体符号在哪_Wingdings特殊字符及符号对照表
  15. 百度地图获取地区/省市县json地图区域数据
  16. C++ Builder初学问与答
  17. 大数据框架复习-flink
  18. 理解TextView三部曲之番外篇:或许这会是最终的进化
  19. SaaS模式金融危机显威力 呼叫中心进入云时代
  20. c语言两个线性表la lb,假设有两个集合A和B分别用两个线性表LA和LB表示,即.ppt

热门文章

  1. 录制电脑桌面的gif图工具 GifCam
  2. 牛客网-密码检查-小明同学最近开发了一个网站,在用户注册账户的时候,需要设置账户的密码,为了加强账户的安全性,小明对密码强度有一定要求:。。。。。
  3. 锁头锁具智能门锁网站搭建模板
  4. spring 项目排查内存泄露,老年代内存不断增长,分区占100%
  5. 计算机体系结构的主要原理,《计算机组成原理》计算机体系结构.pdf
  6. vue中v-model详解
  7. attachment_fu 已是昨日黄花,今朝请用paperclip
  8. SpringBoot访问静态资源(图片)
  9. 有趣且重要的JS知识合集(18)浏览器实现前端录音功能
  10. 博客新地址http://zhen217.iteye.com/