
jwt包含三部分,


第一部分:头部,主要包含了类型和加密方式
第二部分:载荷(存放有效信息的地方)base64编码
第三部分:将headr和paylode两部分用.拼接通过header中的加密方式进行加密
怎么使用?
第一步,引入依赖

创建jwt对象:JwtBuilder
JwtBuilder jwtBuilder=Jwts.builder();
time是毫秒,事先定义一个变量,


接下来对jet令牌进行解密:

public class Jwt {
private long time=1000*60*60*24;//这是定义token过期时间
private String signature="admin";//秘钥
@Test
public void test() {
JwtBuilder jwtBuilder= Jwts.builder();//创建一个JwtBuilder对象
String token = jwtBuilder
//headers
.setHeaderParam("typ","JWT")
.setHeaderParam("alg","HS256")
//payload
.claim("username","tom")
.claim("role","admin")
.setSubject("jwt-test")
.setExpiration(new Date(System.currentTimeMillis()+time))
.setId(UUID.randomUUID().toString())
//signature
.signWith(SignatureAlgorithm.HS256, signature)
.compact();
}
}
十、JWT
1.JWT的简介
1>什么是JWT
Json Web Token(JWT),是一种⽤于通信双⽅之间传递信息的简洁的、安全的声明规范;作为⼀个开放的标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方之间以Json对象的形式安全的传递信息。
JWT一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息,即传递Token,以便于从资源服务器获取资源;特别适用于分布式站点的单点登录(SSO)场景。
官网:https://jwt.io
2>跨域认证
例如,A网站和B网站是同一家公司的关联服务,现在要求,用户只要在其中一个网站登录,再访问另一个网站就无需登录。如何实现?
1)方案一
将Token持久化,保存到持久层;所有服务收到请求后,都从持久层获取Token进行校验。这种方案的优点是架构清晰;缺点是工程量比较大,另外,持久层万一挂了,就会单点失败。

2)方案二
数据库不再保存 Token了,所有Token都保存在客户端,每次请求都将Token发回服务器,服务器解析校验就行了。JWT就是这种方案的一个代表。

3>总结
JWT是一种用于传递Token的解决方案,而且可以无需持久化Token实现跨域认证。
通俗来讲,JWT是一个含签名并携带用户相关信息的加密串,客户端请求服务端时,请求中携带JWT串到服务端,服务端通过签名加密串匹配校验,保证信息未被篡改,校验通过则认为是可靠的请求,将正常返回数据。
2.JWT的原理
JWT的原理是,服务端认证通过以后,会生成一个JSON对象,发回给客户端,就像下面这样:
| { “姓名”: “张三”, “角色”: “管理员”, “到期时间”: “2018年7月1日0点0分” } |
之后,客户端与服务端通信的时候,都要发回这个JSON对象给服务端,服务端完全只靠这个JSON对象认定用户身份。为了防止用户篡改数据,服务端在生成这个JSON对象的时候,还会加上签名。服务端就不保存任何数据了,即服务端变成无状态了,从而比较容易实现扩展。
3.JWT的数据结构

它是一个很长的字符串,中间用点(.)分隔成三个部分。
1> Header(头部)
2> Payload(载体)
3> Signature(签名)

1>Header(头部)
Header部分是一个JSON对象,描述了JWT的元数据,通常是下面的样子:
{
“alg”: “HS256”,
“typ”: “JWT”
}
alg属性表示签名用的算法(algorithm),默认是HMAC SHA256(写成HS256);
typ属性表示这个令牌(token)的类型(type),JWT统一写为JWT;
最后,将上面的JSON对象使用 Base64URL编码转成字符串。
2>Payload(载体)
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段供选用:
sub(subject):主题
iat(issuedAt):签发时间
exp(expiresAt):过期时间
iss(issuer):签发人
aud(audience):受众
nbf(notBefore):生效时间
jti(jwtId):编号
除了官方字段,还可以在这个部分定义私有字段,例如:
{
“sub”: “1234567890”,
“name”: “John Doe”,
“admin”: true
}
JWT默认是不加密的,任何人都可以读到,所以不要把秘密信息(密码,手机号等)放在这个部分;但也是可以加密的,生成原始Token以后,可以用密钥再加密一次。
这个JSON对象也要使用Base64URL编码转成字符串。
3>Signature(签名)
Signature部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。
然后,使用Header里面指定的算法(HMAC SHA256),按照下面的公式产生签名:
HMACSHA256(
base64UrlEncode(header) + “.” +
base64UrlEncode(payload),
secret
)
最后,算出签名以后,把Header、Payload、Signature三个部分拼成一个字符串,每个部分之间用点(.)分隔,就可以返回给用户了。
4.JWT的传递方式
客户端收到服务端返回的JWT串后,可以储存在Cookie里面,也可以储存在localStorage。
此后,客户端每次请求服务端,请求中都要带上这个JWT串。可以把它放在Cookie里面自动发送,但是这样不能跨域,所以更好的做法是放在请求头Authorization里面,或放在POST请求的数据体里面。
5.JWT的API
创建一个maven工程:



添加jwt的依赖:
pom.xml:
| <?xml version=”1.0″ encoding=”UTF-8″?> <project xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”> <modelVersion>4.0.0</modelVersion> <groupId>com.mmy</groupId> <artifactId>jwt-demo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!–jwt依赖–> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.11.0</version> </dependency> </dependencies> </project> |
编码操作:
src/main/java/com.mmy.jwt.Demo.java:
| package com.mmy.jwt; public class Demo { public static void main(String[] args) { /* eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. eyJzdWIiOiJ1c2VyLWluZm8iLCJuYW1lIjoibGlzaSIsImlkIjoxMDEsImV4cCI6MTY1NjgyMzU1MywiaWF0IjoxNjU2ODIzNDMzfQ. IghmOPUVvQCGAtXUZaA4udE-4A7h_RCr3mDkID6qlm0 */ System.out.println(createToken()); parseToken(createToken());//101 lisi } //生成jwt加密串 — token public static String createToken(){ //创建Map<String,Object>封装Header信息 Map<String,Object> header = new HashMap<>(); header.put(“alg”, “HS256”);//签名用的算法 header.put(“typ”, “JWT”);//token类型,统一为JWT //当前时间 — 签发时间 Date createTime = new Date(); //两小时后的时间 — 过期时间 Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MINUTE, 2); Date expireTime = calendar.getTime(); String token = JWT.create() //设置Header .withHeader(header) //设置Payload(载体) .withSubject(“user-info”)//设置主题 .withIssuedAt(createTime)//设置签发时间 .withExpiresAt(expireTime)//设置过期时间 .withClaim(“id”, 101)//设置私有字段id .withClaim(“name”, “lisi”)//设置私有字段name //设置Signature(签名) .sign(Algorithm.HMAC256(“mmy-123”));//指定秘钥为mmy-123 return token; } //解析jwt加密串 public static void parseToken(String token){ //指定秘钥拿到JWT解析器 JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(“mmy-123”)).build(); //传递jwt加密串(token),拿到解析后的jwt串 DecodedJWT decodedJWT = jwtVerifier.verify(token); //从解析后的jwt串中获取相关信息 Claim idClaim = decodedJWT.getClaim(“id”);//用户id–私有字段id System.out.println(idClaim.asInt()); Claim nameClaim = decodedJWT.getClaim(“name”);//用户名–私有字段name System.out.println(nameClaim.asString()); } } |