jwt和传统session的区别?

传统的session认证

1、用户向服务器发送用户名和密码。

2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

3、服务器向用户返回一个 session_id,写入用户的 Cookie。

4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

基于session认证所显露的问题。

这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。

举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?

一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

基于token的鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

流程上是这样的:

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据

这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *。

JWT长什么样?

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

  • 第一部分我们称它为头部(header)
  • 第二部分我们称其为载荷(payload, 类似于飞机上承载的物品)
  • 第三部分是签证(signature).

header


jwt的头部承载两部分信息:

   {'typ': 'JWT','alg': 'HS256'}

声明类型,这里是jwt
声明加密的算法 通常直接使用 HMAC SHA256

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

playload


载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明
  • 标准中注册的声明 (建议但不强制使用) :

iss: jwt签发者
sub: 主题
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 生效时间
iat: 签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

  • 公共的声明 :
    公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

  • 私有的声明 :
    私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

定义一个payload:

{"sub": "1234567890","name": "John Doe","admin": true
}

然后将其进行base64加密,得到Jwt的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
signature

Signature


  • header (base64后的)
  • payload (base64后的)
  • secret
    这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
    将这三部分用.连接成一个完整的字符串,构成了最终的jwt
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

jjwt如何应用


我们如果把token理解问一个携带信息的加密字符,那大致可以分为3个步骤

  • 向token中加入信息
  • 把信息加密
  • 解密获取信息

项目结构

jwt核心代码

public class JwtHelper {/*** token 过期时间, 单位: 秒. 这个值表示 30 天*/private static final long TOKEN_EXPIRED_TIME = 30 * 24 * 60 * 60;/*** jwt 加密解密密钥*/private static final String JWT_SECRET = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=";public static final String jwtId = "tokenId";/*** 创建JWT*/public static String createJWT(Map<String, Object> claims, Long time) {SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。Date now = new Date(System.currentTimeMillis());SecretKey secretKey = generalKey();long nowMillis = System.currentTimeMillis();//生成JWT的时间//下面就是在为payload添加各种标准声明和私有声明了JwtBuilder builder = Jwts.builder() //这里其实就是new一个JwtBuilder,设置jwt的body.setClaims(claims)          //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的.setId(jwtId)                  //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。.setIssuedAt(now)           //iat: jwt的签发时间.signWith(signatureAlgorithm, secretKey);//设置签名使用的签名算法和签名使用的秘钥if (time >= 0) {long expMillis = nowMillis + time;Date exp = new Date(expMillis);builder.setExpiration(exp);     //设置过期时间}return builder.compact();}/*** 验证jwt*/public static Claims verifyJwt(String token) {//签名秘钥,和生成的签名的秘钥一模一样SecretKey key = generalKey();Claims claims;try {claims = Jwts.parser()  //得到DefaultJwtParser.setSigningKey(key)         //设置签名的秘钥.parseClaimsJws(token).getBody();} catch (Exception e) {claims = null;}//设置需要解析的jwtreturn claims;}/*** 由字符串生成加密key** @return*/public static SecretKey generalKey() {String stringKey = JWT_SECRET;byte[] encodedKey = Base64.decodeBase64(stringKey);SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");return key;}/*** 根据userId和openid生成token*/public static String generateToken(String openId, Integer userId) {Map<String, Object> map = new HashMap<>();map.put("userId", userId);map.put("openId", openId);return createJWT(map, TOKEN_EXPIRED_TIME);}}

Controller层


@RestController
public class LoginController {@RequestMapping("/user/login")public String login() {String jwtToken = JwtHelper.generateToken("123",456);return jwtToken;}@RequestMapping("user/hello")public String user(){return   "hello";}
}

过滤器的使用


public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request =(HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;String token = request.getHeader("authorization"); //获取请求传来的tokenClaims claims = JwtHelper.verifyJwt(token); //验证tokenif (claims == null) {  response.getWriter().write("token is invalid");}else {filterChain.doFilter(request,response);}}@Overridepublic void destroy() {}
}

过滤器的加载


@Configuration
public class BeanRegisterConfig {@Beanpublic FilterRegistrationBean createFilterBean() {//过滤器注册类FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter());registration.addUrlPatterns("/user/hello"); //需要过滤的接口return registration;}
}

启动项目: 访问localhost:8080/user/hello
如下图:

携带token访问/user/hello

springboot-jjwt相关推荐

  1. springboot中JJWT的简单使用

    springboot中JJWT的简单使用 一 什么是JWT jwt全称json web token,是基于json协议的用于结局认证授权的方法.token就是令牌,其主要作用是用来进行授权(Autho ...

  2. SpringBoot 通过jjwt快速实现token授权

    1.首先理解jwt是什么 jwt:全称(JSON Web Token),是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.是目前最流行 ...

  3. springboot 配置 jjwt

    JWT 全名 JSON WEB Token 主要作用为用户身份验证, 广泛应用与前后端分离项目当中. JWT 的优缺点 : https://www.jianshu.com/p/af8360b83a9f ...

  4. 跟我学Springboot开发后端管理系统8:Matrxi-Web权限设计实现

    上篇文章讲述了Matrix-web整体实现的权限控制的思路.现在来回顾一下: 首先,用户需要登录,填用户名.密码,后端接收到登录请求,进行用户.密码的校验,校验成功后则根据用户名生成Token,并返回 ...

  5. springboot 集成jwt设置过期时间_传说中的jwt,我们来征服一下

    原创:猿逻辑,欢迎分享,转载请保留出处. 本文的完整示例代码,见github仓库.小q只在文中介绍最关键的代码块. https://github.com/yuanluoji/purestart-spr ...

  6. SpringBoot + Redis 解决海量重复提交问题

    作者 | 慕容千语 来源 | https://www.jianshu.com/p/c806003a8530 前言 在实际的开发项目中,一个对外暴露的接口往往会面临很多次请求,我们来解释一下幂等的概念: ...

  7. java不同项目加token访问_实战:你用SpringBoot集成JWT来实现一下token验证,可否?...

    作者:意识流 来源:www.jianshu.com/p/e88d3f8151db JWT官网:https://jwt.io JWT(Java版)的github地址:https://github.com ...

  8. Shiro和SpringBoot简单集成

    Shiro是一种简单的安全框架,可以用来处理系统的登录和权限问题. 本篇记录一下Spring Boot和Shiro集成,并使用Jwt Token进行无状态登录的简单例子. 参考Demo地址,此Demo ...

  9. SpringBoot+Vue博客系统---后端接口开发

    Java后端接口开发 从零开始搭建一个项目骨架,最好选择合适,熟悉的技术,并且在未来易拓展,适合微服务化体系等.所以一般以Springboot作为我们的框架基础,这是离不开的了. 然后数据层,我们常用 ...

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

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

最新文章

  1. O太多,具体都代表什么呢?
  2. java 8大happen-before原则超全面详解
  3. FGPM:文本对抗样本生成新方法
  4. BZOJ 2286 消耗战 (虚树+树形DP)
  5. [USACO08DEC]拍头Patting Heads 数学 BZOJ 1607
  6. Spring Security源码分析之LogoutFilter
  7. 社会计算:服务群体社会的大数据科学
  8. NB-IOT技术以及物联网安全问题简述
  9. JSONObject和JSONArray使用
  10. 三表联查,这是我目前写过的最长的sql语句,嗯嗯,果然遇到问题才能让我更快成长,更复杂的语句也有了一些心得了...
  11. ios 绘制线框_iOS中画矩形的几种方法总结
  12. kycms1.3.0命令执行利用
  13. Excel加载宏.xla文件的使用方法
  14. 51单片机程序设计——电子音乐盒
  15. Oracle 触发器写法
  16. 解决undefined reference to `WinMain'
  17. 微信VS抖音_四大品类投放分析报告——护肤、彩妆、美食饮品、母婴用品
  18. 基恩士KV8000程序 基恩士KV8000,威伦通触摸屏,搭载KV-XH16EC总线模块进行分布式总线控制
  19. Unity做一个太阳系
  20. 必学框架新版SpringBoot教程(下集)

热门文章

  1. 软件测试过程及V模型
  2. 并集、交集、差集 Sql总结
  3. 自定义下拉框样式,利用prototype制作
  4. jstack命令的使用
  5. Python Web开发框架之Django篇——二、Django连接MySQL数据库以及建表的操作
  6. 第五人格共研服服务器正在维护,《第五人格》11月13日共研服更新了什么 共研服更新内容汇总...
  7. 三行代码把女朋友照片变成了素描图片!Python竟然还能这样
  8. 2021年全国研究生数学建模竞赛华为杯B题空气质量预报二次建模求解全过程文档及程序
  9. 2014驾照流程(约6个月)
  10. Js中Object方法