首页 > 编程知识 正文

jwt生成的token安全吗,token ring工作原理

时间:2023-05-04 19:09:03 阅读:41799 作者:99

资料来源: www.cn blogs.com/better-farther-world 2099

另一方面,jwtJSONwebToken(jwt )是基于JSON的开放标准,被执行用于在网络APP应用环境之间传递声明) (RFC 7519 )。

此token设计紧凑、安全,特别适用于分布式站点的单点登录(SSO )场景。

JWT声明通常用于在身份提供方和服务提供方之间传递经过身份验证的用户标识,以便于从资源服务器检索资源。 此外,还可以向其他业务逻辑添加所需的声明信息。 token可以直接用于身份验证,也可以加密。

二、JWT的组成1、 JWT生成代码后的情况ey j0 exaioijkv1qilcjhbgcioijiuzi1nij9. eyjzdwiioiixmjm0nty3odkwiibmftzsi6ikpvag4grg9liwiywrtaw4ionrydwv9. uqmqauhuhuhu JWT由三部分组成,第一部分称为头部(header ),第二部分称为载荷(payload ),就像在飞机上一样),第三部分为签证(signature )。

header

jwt的头上有两个信息:

声明类型,这里是jwt

声明加密的算法通常直接使用HMAC SHA256

完整的头部如下所示:

{'typ':'JWT ',' alg':'HS256'}并对报头进行base64加密,该加密可以对称解密},构成了第一部分

ey j0 exaioijkv1qilcjhbgcioijiuzi1nij 9http://www.Sina.com /

载荷是指存储有效信息的地方。 这个名字就像是指飞机上的商品,这些有效信息包括三个部分

标准注册的声明

公共声明

私人声明

标准注册声明(建议但不强制使用) :

iss: jwt发行人

sub: jwt目标用户

aud:接收jwt的一侧

exp: jwt的到期日期。 这个有效期限必须大于发行时间

nbf:定义在什么时候之前不能使用此jwt。

iat: jwt的发行时间

jti: jwt的唯一id主要用作一次性token,以避免重放攻击。

公共声明:

的声明可以添加任何信息,一般添加用户的相关信息和其他业务所需的信息。 但是,不建议追加机密信息。 这是因为该部分可以在客户端解密。

私人声明:

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

定义payload:

{'sub':'1234567890 ',' name':'JohnDoe ',' admin':true}并对其进行base64加密,得到Jwt的第二部分

eyjzdwiioiixmjm0nty3odkwiiwibmftzsi6ikpvag4grg9liiwiywrtaw4ionrydwv 9http://www.Sina.com /

jwt的第三部分是签证信息,该签证信息由三部分组成:

Header(Base64之后的) ) ) ) ) ) ) ) ) ) ) ) )。

Pyload(Base64之后的) ) ) ) ) )。

安全保护

该部分需要使用用base64加密的header和用base64加密的payload由.连接构成的字符串,通过用header声明的加密方式进行加盐secret的组合加密,构成了jwt的第三部分。

uqmqauhurpdvv2ST7mzkyltomvfg7sykejmddi5xf8 q密钥secret存储在服务器端,服务器端将根据该密钥生成和验证token,因此必须对其进行保护。

3、签名目的最后签名的过程实际上是在头部和载荷内容上签名。 一般来说,加密算法的输出因输入而异。 对于两个不同的输入,相同输出发生的概率很小(可能小于我成为xqdjz的概率)。 所以,“不同的输入产生不同的输出”是必然的事情吧。 推荐: Java面试习题宝典

因此,如果有人对报头或有效载荷的内容进行解码、修改和编码,则新报头或有效载荷的签名将与以前的签名不同。 而且,如果不知道服务器加密时使用的密钥,得到的签名也应该不同。

服务器APP应用程序接收到JWT后,首先使用相同的算法对头部和载荷内容再次签名。 那么,我们如何知道服务器APP应用程序使用的是哪个算法呢? 请不要忘记。 我们在JWT的脑子里已经在alg字段里展示了我们的加密算法。

如果服务器APP应用程序再次以相同的方式在头部和载荷上签名,然后发现自己计算的签名

名和接受到的签名不一样,那么就说明这个Token的内容被别人动过的,我们应该拒绝这个Token,返回一个HTTP 401 Unauthorized响应。

注意:在JWT中,不应该在载荷里面加入任何敏感的数据,比如用户的密码。

4、如何应用

一般是在请求头里加入Authorization,并加上Bearer标注:

fetch('api/user/1', {  headers: {    'Authorization': 'Bearer ' + token  }})

服务端会验证token,如果验证通过就会返回相应的资源。

5、安全相关

不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。

保护好secret私钥,该私钥非常重要。

如果可以,请使用https协议

6、对Token认证的五点认识

一个Token就是一些信息的集合;

在Token中包含足够多的信息,以便在后续请求中减少查询数据库的几率;

服务端需要对cookie和HTTP Authrorization Header进行Token信息的检查;

基于上一点,你可以用一套token认证代码来面对浏览器类客户端和非浏览器类客户端;

因为token是被签名的,所以我们可以认为一个可以解码认证通过的token是由我们系统发放的,其中带的信息是合法有效的;

三、传统的session认证

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

但是这种基于session的认证使应用本身很难得到扩展,随着不同客户端用户的增加,独立的服务器已无法承载更多的用户,而这时候基于session认证应用的问题就会暴露出来。推荐:Java面试练题宝典

基于session认证所显露的问题

Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。

扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。

CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

基于token的鉴权机制

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

流程上是这样的:

用户使用用户名密码来请求服务器

服务器进行验证用户的信息

服务器通过验证发送给用户一个token

客户端存储token,并在每次请求时附送上这个token值

服务端验证token值,并返回数据

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

四、token的优点

支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输。

无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息。

更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可。

去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可。

更适用于移动应用: 彩色的小馒头的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。

CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。

性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多。

不需要为登录页面做特殊处理: 如果你使用Protractor 做功能测试的时候,不再需要为登录页面做特殊处理。

基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)。

因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。

因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。

便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。

它不需要在服务端保存会话信息, 所以它易于应用的扩展。

五、JWT的JAVA实现

Java中对JWT的支持可以考虑使用JJWT开源库;JJWT实现了JWT, JWS, JWE 和 JWA RFC规范;

下面将简单举例说明其使用:

1、生成Token码

import javax.crypto.spec.SecretKeySpec;import javax.xml.bind.DatatypeConverter;import java.security.Key;import io.jsonwebtoken.*;import java.util.Date;     //Sample method to construct a JWT private String createJWT(String id, String issuer, String subject, long ttlMillis) { //The JWT signature algorithm we will be using to sign the tokenSignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; long nowMillis = System.currentTimeMillis();Date now = new Date(nowMillis); //We will sign our JWT with our ApiKey secretbyte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(apiKey.getSecret());Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());   //Let's set the JWT ClaimsJwtBuilder builder = Jwts.builder().setId(id)                                .setIssuedAt(now)                                .setSubject(subject)                                .setIssuer(issuer)                                .signWith(signatureAlgorithm, signingKey); //if it has been specified, let's add the expirationif (ttlMillis >= 0) {    long expMillis = nowMillis + ttlMillis;    Date exp = new Date(expMillis);    builder.setExpiration(exp);} //Builds the JWT and serializes it to a compact, URL-safe stringreturn builder.compact();}

2、解码和验证Token码

import javax.xml.bind.DatatypeConverter;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.Claims; //Sample method to validate and read the JWTprivate void parseJWT(String jwt) {//This line will throw an exception if it is not a signed JWS (as expected)Claims claims = Jwts.parser()           .setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret()))   .parseClaimsJws(jwt).getBody();System.out.println("ID: " + claims.getId());System.out.println("Subject: " + claims.getSubject());System.out.println("Issuer: " + claims.getIssuer());System.out.println("Expiration: " + claims.getExpiration());}

文章整理自:

https://blog.csdn.net/buyaoshuohua1/article/details/73739419

https://www.cnblogs.com/xiekeli/p/5607107.html#top

https://blog.csdn.net/SoftwareOscar/article/details/78538346

https://blog.csdn.net/Jack__Frost/article/details/64964208

http://blog.leapoahead.com/2015/09/06/understanding-jwt/

推荐好文强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。