我们的授权方案是 SpringCloud + Security + Oauth2 + JWT 为了方便后面做认证授权先来普及两个概念Oauth2和JWT
Oauth2部分 1.JWT概述 1.1.什么是JWTJSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。
JWT 以 JSON 对象的形式安全传递信息。因为存在数字签名,因此所传递的信息是安全的。客户端身份经过服务器验证通过后,会生成带有签名的 JSON 对象并将它返回给客户端。客户端在收到这个 JSON 对象后存储起来。
在以后的请求中客户端将 JSON 对象连同请求内容一起发送给服务器,服务器收到请求后通过 JSON 对象标识用户,如果验证不通过则不返回请求的数据。
总结:使用JWT生产的Token是安全的,它实现了数据的安全传输,并且Token中可以携带认证信息,做到真正的无状态,是“客户端Token”模式授权方案的不二选择
1.2.JWT特点- 基于JSON,方便解析
- 可以在令牌中定义内容,方便扩展
- 非对称加密算法即数字签名,JWT防篡改
- Token携带认证信息,无效访问认证服务器即可完成权限校验,做到“无状态”
JWT包含三部分组成
-
头部 (header): JSON格式,描述JWT的最基本的信息,如签名算法等效果如下:
{"typ":"JWT","alg":"HS256"}
这里指明了签名算法是HS256算法。在使用过程中会对该 JSON进行BASE64编码如:yJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
-
载荷(playload) : JSON格式,包含了需要的数据内容,也需要BASE64编码。包含三部分 标准中注册的声明(建议但不强制使用)
iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: jwt的过期时间,这个过期时间必须要大于签发时间 nbf: 定义在什么时间之前,该jwt都是不可用的. iat: jwt的签发时间 jti: jwt的唯一身份标识,主要用来作为一次性token。
公共的声明 :公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.
私有的声明 :私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。 定义一个payload: 如
{"sub":"1234","name":"xxx","admin":true}
进行Base64编码后得到JWT第二部分如eyJzdWIiOiIxMjM0NTY3ODkbmFtZSI6IkpvaG4gRG9lIiwiYW...
-
签名 (signature): 通过指定的算法生成哈希,以确保数据不会被篡改。jwt的第三部分是一个签证信息,通过指定的算法生成哈希,以确保数据不会被篡改,这个签证信息由三部分组成:head(base64编码后的);playload(base64编码后的);secret(秘钥)签名后的密文构成JWT第三部分如:
ThecMfgYjtoys3JX7dpx3hu6pUm0piZ0tXXr
最后JWT构建的内容编码后的字符串eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDQxODF9.ThecMfgYjtoys3JX7dpx3hu6pUm0piZ0tXXreFU_u3Y
首先我们来加入JWT的依赖
io.jsonwebtoken
jwt
0.9.0
令牌的签发
//系统时间
long now=System.currentTimeMillis();
//计算过期时间30秒过期
long exp=now+1000*30;
//使用Jwts签发令牌
JwtBuilder jwtBuilder = Jwts.builder().setId( "111" ) //设置唯一编号
.setSubject( "zs" ) //主题,可以扔一个JSON
.setIssuedAt( new Date() )//签发时间
.setExpiration( new Date( exp ) )//过期时间
.claim( "roles","admin" ) //扩展数据,角色
.signWith( SignatureAlgorithm.HS256, "123" ); //使用HS256算法,并设置SecretKey(字符串)
String token = jwtBuilder.compact();
System.out.println(token);
打印一个很长的密文:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDQxODF9.ThecMfgYjtoys3JX7dpx3hu6pUm0piZ0t...
解析令牌
String token ="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NjIyNTM3NTQsImV4cCI6MTU2MjI1Mzc4Mywicm9sZXMiOiJhZG1pbiJ9.CY6CMembCi3mAkBHS3ivzB5w9uvtZim1HkizRu2gWaI";
Claims claims = Jwts.parser().setSigningKey( "123" ).parseClaimsJws( token ).getBody();
System.out.println(claims); //扩展数据
System.out.println(claims.get( "roles" )); //角色信息
打印效果{jti=111, sub=zs…}
总结最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?