jwt, json web token

jwt

  • 1. JWT
    • 什么是JWT
    • JWT能做什么
    • 为什么用JWT
    • JWT结构
    • JWT问题和趋势
  • 2. jwt加解密工具,使用
    • pom
    • 工具类
    • 测试

1. JWT

  1. 什么是JWT

    1. 官方定义 json web token是一个开放标准(rfc7519),它定义了一种紧凑的,自包含的方式,用于在各方之间以JSON对象安全的传输信息,此信息可以验证和信任,因为它是数字签名的。jwt可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥、私钥进行签名。
    2. 通俗解释 JWT简称JSON Web Token,也就是通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输,在传输过程中还可以完成数据加密、签名等相关处理。
  2. JWT能做什么

    1. 授权
      1. 这是使用JWT的最常见的方案,一旦用户登录成功,系统生成一个JWT传递给用户,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。
    2. 信息交换
      1. JSON Web Token是在各方之间安全的传输信息的好方法,因为可以对JWT进行签名,所以您可以确保发件人是所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否被篡改。
  3. 为什么用JWT

    1. 基于传统的session认证

      1. 我们知道http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能说明是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为 cookie,以便下次请
        求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证
    2. 认证流程

      1. cookie session
    3. 暴露的问题

      1. 每个用户经过我们的应用认证之后,我们的应用都要在服务做一次记录,以方便用户下次请求的别,通常而言session都是保存在内存中,而随着认证用户的增多,服务器的开销会明显增大
      2. 用户认证之后,服务器做认证记录,如果认证的记录被保存在内存中的话,这意妹着用户下次请求还必项要请求在这台服务器上,这样才能拿到授权的源,这样在分布式的应用上,相应的限制了负载均衡的能力,这也意味着限制了应用的扩属能力
      3. 因为是基于 cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击
      4. 在前后端分离系统中就更加痛苦:前后端分离在应用解耦后增加了部署的复杂性,通常用户一次请求就要转发多次,如果用session每次携带 sessionid到服务器,服务器还要查询用户信息,如果同时用户很多,这些信息存储在服务器内存中,给服务器增加负担,还有就是CSRF(跨站请求伪造的攻击,session是基于 cookie进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击,还有就是
        sessionid就是一个特征值,表达的信息不够丰富,不容易扩展,而且如果你后端应用是多节点部署,那么就需要实现 session共享机制,不方便集群应用
    4. 基于JWT认证

      1. 认证流程

      1. 认证流程

        1. 首先通过表单将自己的用户名和密码发送到后端的接口,这一过程一般是一个HTTP POST请求,建的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。
        2. 后端核对用户名和密码成功后,将用户的id等其他信息作为 JWT Payload(负载),将其与头部分别进行bas64编码拼接后签名,形成一个JWT( Token),形成的JWT就是一个形同111.zzz,xxx的字符串
        3. token head. payload. singurater
        4. 后端将JWT作为登录成功的返回结果返回给前端,前端可以将返回的结果保存在localStorage或sessionStorage上,退出登录时前端删除保存的JWT即可。
        5. 前端在每次请求时将JWT放入 Http Header中的 Authorization位,(解决XSS和XSRF问题) HEADER
        6. 后端检查是否存在,如存在验证JWT的有效性,例如,检查签名是否正确:检查 Token是否过期:检查Token的接收方是否是自己(可选)
        7. 验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。
      2. JWT优势

        1. 简洁:可以通过URL,POST参数或者在 HTTP header发送,因为数据量小,传输速度也很快
        2. 自包含:负载中包含了所有用户所需要的信息,避免了多次查询数据库
        3. 因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持
        4. 不需要在服务器保存会话信息,特别适用于分布式微服务。
  4. JWT结构

    1. 令牌组成

      1. 标头( Header)
      2. 有效负载( Payload)
      3. 签名( Sionature)
        因此,JWT通常如下所示:xxx.yyy.zzz
    2. Header
      标头通常由两部分组成:令牌的类型(即JWT和所使用的签名算法,例如HMAC SHA256或RSA,它会使Base64编码组成JWT结构的第一部分。
      注意:Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程

      {"alg":"HS256","typ":"JWT"
      }
      
    3. Payload
      令牌的第二部分是有效负载,其中包含声明,声明是有关实体(通常是用户)和其他数据的声明。同样的,它会使用Base64编码组成
      JWT结构的第二部分

      {"id":666,"name":"bitqian666","age":19
      }
      
    4. Signature
      前面两部分都是使用Base64进行编码的,即前端可以解开知道里面的信息, Signature需要使用编码后的 header和 payload以及我们提供的一个密钥,然后使用 header中指定的签名算法(HS256)进行签名,签名的作用是保证JWT没有被慕改过

    5. 签名目的
      最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被窜改。如果有人对头部以及负载的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的
      如果要对新的头部和负载进行签名,在不知道服务器加密时使用的密钥的话,得出来的签名也是不一样的

    6. 信息安全问题
      在这里大家一定会问一个问题:Base64是一种编码,是可逆的,那么我的信息不就被暴露了吗?
      是的。所以,在JWT中,不应该在负载里面加入任何敏感的数据。比如,我们传输的是用户的 User ID,这个值实际上不是什么敏感内容,一般情况下被知道也是安全的。但是像密码这样的内容就不能被放在JWT中了。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的密码了。因此JWT适合用于向Web应用传递一些非敏感信息。JWT还经常用于设计用户认证和授权系统,甚至实现web应用的单点登录。

  5. JWT问题和趋势

    1. JWT默认不加密,但可以加密。生成原始令牌后,可以使用改令牌再次对其进行加密。
    2. 当JWT未加密方法时,一些私密数据无法通过JWT传输。
    3. JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
    4. JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
    5. JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
    6. 无感刷新JWT,后端接收JWT解析获取过期时间,如果快过期,生成新的令牌(业务数据和之前一致)
    7. 为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。

2. jwt加解密工具,使用

pom

 <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.10.3</version></dependency>

工具类

package top.bitqian.config;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;/*** @author echo lovely* @date 2020/12/4 21:46*/public class JwtUtil {//密钥(不能泄露 、可多次加盐加密再存在合适的地方)public static final String SECRET = "defAu&TJHVhc$%WW^JJG";//过期时间:秒public static final int EXPIRE = 300;/*** JWT 添加至HTTP HEAD中的前缀*/private static final String JWT_SEPARATOR = "Bearer ";/*** 生成Token* @param  userName userName* @param userPwd userPwd* @return token token* @throws Exception create token ex*/public static String createToken(String userName, String userPwd) throws Exception {try {//日历对象//当前时间Calendar nowTime = Calendar.getInstance();//加30秒nowTime.add(Calendar.SECOND, EXPIRE);Date expireDate = nowTime.getTime();//标头 可以不写,默认值就是下方所定义的mapMap<String, Object> map = new HashMap<>();// 算法map.put("alg", "HS256");// 类型 jwt加密map.put("typ", "JWT");return  JWT.create().withHeader(map)//头 有默认值 可以不写//负载 业务数据.withClaim("userPwd", userPwd).withClaim("userName", userName).withClaim("myId", "aa").withSubject("subject")//可以不写.withIssuedAt(new Date())//签名时间.withExpiresAt(expireDate)//过期时间.sign(Algorithm.HMAC256(SECRET));//签名} catch (Exception e) {throw new Exception(e);}}/*** 验证Token* @param token token* @return token map* @throws RuntimeException 凭证已过期,请重新登录*/public static Map<String, Claim> verifyToken(String token) throws RuntimeException {JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();DecodedJWT jwt;try {jwt = verifier.verify(token);}catch (Exception e){throw new RuntimeException("凭证已过期,请重新登录");}return jwt.getClaims();}/*** 解析Token* @param token token* @return claim*/public static Map<String, Claim> parseToken(String token){DecodedJWT decodedJWT = JWT.decode(token);return decodedJWT.getClaims();}}

测试

    public static void main(String[] args){try {// 创建token,传入参数String token = JwtUtil.createToken("your token param", "your token param");// 获取tokenSystem.out.println("token=" + token);//Thread.sleep(5000);Map<String, Claim> map = JwtUtil.verifyToken(token);//Map<String, Claim> map = JwtUtil.parseToken(token);//遍历for (Map.Entry<String, Claim> entry : map.entrySet()){if (entry.getValue().asString() != null){System.out.println(entry.getKey() + "===" + entry.getValue().asString());}else {System.out.println(entry.getKey() + "===" + entry.getValue().asDate());}}}catch (Exception e){e.printStackTrace();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序结合Java后端实现登录注册

微信小程序登录微信用户&#xff0c;授权信息&#xff0c;相关实体类微信用户表实体类获取微信的token常量抽取httpClient工具&#xff0c;用于发送请求获取tokennbplus pom工具类请求微信后台&#xff0c;获取openid&#xff0c;返回的是json登录或者注册完整业务实现&#xf…

consul作为服务注册中心

consulconsul下载地址providerorderconsul 由go语言编写的一款优秀的服务注册中心应用。 https://www.consul.io/intro/index.html 中文文档 功能&#xff1a; 1. 服务发现 提供HTTP和DNS两种发现方式 2. 健康监测 支持多种协议&#xff0c;HTTP、TCP、Docker、Shell脚本定制…

ribbon, restTemplate 负载均衡服务调用

ribbonribbon conceptribbon核心组件IRule模仿源码重写轮询ribbon concept spring cloud ribbon 是基于Netflix ribbon实现的一套客户端负载均衡的工具。 简单的说&#xff0c; Ribbon是Netflix发布的开源项目&#xff0c; 主要功能是提供客户端的软件负载均衡算法和服务 完善的…

ABAP 弹出框自建内容POPUP

可以自己设计内容&#xff0c;仅供参考。转载于:https://www.cnblogs.com/matinal/p/4135269.html

前端学习(1287):node.js的组成

var first hello nodejs; console.log(first);function fn() {console.log("fn函数被调用了"); }fn();for (var i 0; i < 5; i) {console.log(i); }if (true) {console.log(123); } 运行结果

gateway路由网关,zuul的替代品

zuul1 low, zuul2 还没长大呢&#xff0c;不敢用。 gateway 基于netty, spring flux, reactor 异步非阻塞, 快呀。 与spring良好整合, spring社区的呢。官方推荐。https://spring.io/projects/spring-cloud-gateway https://cloud.spring.io/spring-cloud-static/spring-cloud-…

ASP.NET MVC 5 入门教程 (3) 路由route

文章来源&#xff1a; Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc-5-get-started-route.html 上一节&#xff1a;ASP.NET MVC 5 入门教程 (2) 控制器Controller 下一节&#xff1a;ASP.NET MVC 5 入门教程 (4) View和ViewBag 源码下载&#xff1a;点我下载 上一节我…

spring cloud config 配置中心

/(ㄒoㄒ)/~~ 还有好多要学鴨 cloud config分布式面临的系统配置问题&#xff0c;如何解决分为服务端配置与客户端配置客户端不能自动更新git上的配置分布式面临的系统配置问题&#xff0c;如何解决 1. 分布式系统面临的配置问题 微服务意味着要将单体应用中的业务拆分成一个个…

前端学习(1289):nodejs模块化的开发规范

demo02.js const add (n1, n2) > n1 n2exports.add add; demo03.js const a require(./demo02.js); console.log(a); 运行结果

spring cloud bus消息总线

解决的痛点: 当git仓库的配置更新后&#xff0c; cloud config 客户端不能获取到配置信息的问题, 需要手动发送请求&#xff0c;刷新配置。 可以参照 spring cloud config cloud busbus消息总线使用rabbitMQ推送消息原理架构实现使用curl命令刷新客户端的配置bus bus配合conf…

前端学习(1290):nodejs模块化的开发导出另一种方式

demo04.js const greeting _name > hello ${_name};module.exports.greeting greeting; demo05.js const a require(./demo04.js); console.log(a); console.log(a.greeting(geyao)); 运行结果 demo04.js const greeting _name > hello ${_name}; const x 100;…

SpringCloud Stream消息驱动

为啥有这个技术&#xff1f;&#xff1f;&#xff1f; 1. 这个stream是操作消息队列的&#xff0c;简化&#xff0c;学习消息队列的成本降低。 2. 可操作rabbitMQ兔子message queue&#xff0c;kafaka&#xff0c;可理解为jdbc可操作oracle, mysql.. 3. spring家的技术学就完了…

前端学习(1291):nodejs的系统模块文件读取操作

//通过模块对模块进行引入 const fs require(fs); //读取文件 fs.readFile(./demo01.js, utf8, (err, doc) > {console.log(err);console.log(doc); }) 运行结果

解决MySQL忘记root密码

网上有很多关于忘记MySQL root密码的一些文章&#xff0c;里面都有写怎么去解决&#xff0c;但有时觉得写得太恶心&#xff0c;要么一字不漏的抄别人的&#xff0c;要么就说得不清不楚&#xff0c;好了&#xff0c;不吐槽了&#xff0c;以下是解决的整个过程。 首先我们要知道忘…

前端学习(1292):文件写入操作

const fs require(fs);fs.writeFile(./demo.txt, 即将要写入的内容, err > {if (err ! null) {console.log(err);return;}console.log(文件内容写入成功); }) 运行结果

前端学习(1293):系统模块path路径操作

//导入path模块 const path require(path); //路径拼接 const finaPath path.join(public, uploads, avater); console.log(finaPath); 运行结果