当前位置: 首页>后端>正文

JWT案例一

JWT案例一,第1张

有状态登录(session认证)

服务器当中记录每一次的登录信息,从而根据客户端发送的数据来判断登录过来的用户是否合法。

缺点:

每个用户登录信息都会保存到服务器的session中,随着用户的增多服务器的开销会明显增大;

由于session存储在服务器的物理内存当中,所以在分布式系统当中这种方式将会失效。

当然我们也可以通过分布式session来解决相关问题,比如将session信息存储到Redis中,但这无疑会提升系统的复杂度。

因为session认证本质基于cookie,而移动端及非浏览器应用通常没有cookie,故对非浏览器的客户端、手机移动端等不适用;

由于基于cookie,而cookie无法跨域,所以session的认证也无法跨域,对单点登录不适用;

无状态登录(token认证)

服务器当中不记录用户的登录信息,而是将登录成功后的合法用户信息以token方式保存到客户端当中,用户在每次请求都携带token信息。

优点:

减轻服务端存储session的压力;

支持分布式,支持单点登录并对移动端友好;

支持跨域;

JWT及JSON Web Token,是一种在两方之间以紧凑、可验证的形式传输信息的方式。此信息可以验证和信任,因为它是数字签名的。JWT 可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

什么时候使用JWT

授权:这是使用JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小并且能够在不同的域中轻松使用。

信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。因为可以对 JWT 进行签名(例如,使用公钥/私钥对),所以您可以确定发件人就是他们所说的那个人。此外,由于使用标头和有效负载计算签名,您还可以验证内容没有被篡改。

JWT结构

JWT由以( . )分隔的三部分组成,它们是:

标头(Header)

有效荷载(Payload)

签名(Signature)

因此,JWT 通常如下所示:xxxxx.yyyyy.zzzzz。在传输的时候,会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串:

JWTString = Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT 定义了一个标准,JJWT 是 JWT 基于 Java 的一个实现。

<dependency>

<groupId>io.jsonwebtoken</groupId>

<artifactId>jjwt</artifactId>

<version>0.9.1</version>

</dependency>

public class JWTTest01 {

public static void main(String[] args) {

// ???????m1();

m2();

}

static void m1() {

// 生成令牌

JwtBuilder jwtBuilder = Jwts.builder()

.setId("888")//唯一ID

.setSubject("zhao")//接受用户

.setIssuedAt(new Date())//签发时间

.signWith(SignatureAlgorithm.HS512, "1234");//签名算法、和秘钥

// secret key byte array cannot be null or empty.

// key不能太短 最短四个字符!!!

String token = jwtBuilder.compact();

System.out.println("生成令牌:【" + token + "】");

}

static void m2(){

// 解析令牌

String token = "eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiJ6aGFvIiwiaWF0IjoxNjk0MzUyMTk2fQ.cFeamoabpwXcPp49DzHhyOL-LAkpMUiz9Tu-ai7efg6xhTQy1TWpmd0mY6BH2aOEWwZ4dF5wNPFnBM5hTXtm7Q";

Claims claims = (Claims) Jwts.parser()

.setSigningKey("1234")

.parse(token)

.getBody();

System.out.println(claims.getId());

System.out.println(claims.getSubject());

System.out.println(claims.getIssuedAt());

System.out.println("解析令牌:【" + claims + "】");

}

}

public class JWTTest02 {

/**

* 使用JWT令牌时需要注意:

*

* JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的。

* 如果JWT令牌解析校验时报错,则说明 JWT令牌被篡改 或 失效了,令牌非法。

*

* @param args

*/

public static void main(String[] args) {

// ???????m1();

m2();

}

// (1)生成JWT代码实现

public static void m1() {

Map<String, Object> claims = new HashMap<>();

claims.put("id", 1);

claims.put("username", "Tom");

String jwt = Jwts.builder()

.setClaims(claims) //自定义内容(载荷)

.signWith(SignatureAlgorithm.HS256, "itheima") //签名算法

.setExpiration(new Date(System.currentTimeMillis() + 24 * 3600 * 1000)) //有效期

.compact();

System.out.println(jwt);

}

public static void m2() {

Claims claims = Jwts.parser()

.setSigningKey("itheima")//指定签名密钥(必须保证和生成令牌时使用相同的签名密钥)

.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjk0MzIzODExLCJ1c2VybmFtZSI6IlRvbSJ9.VDNnX-n68QjIIRpmL3Ktcj9K5V0UWcPHlp09qA4odk4")

.getBody();

System.out.println(claims);

}

}

public class JwtUtils {

private static String signKey = "zhaoyang";//签名密钥

private static Long expire = 43200000L; //有效时间

/**

* 生成JWT令牌

* @param claims JWT第二部分负载 payload 中存储的内容

* @return

*/

public static String generateJwt(Map<String, Object> claims){

String jwt = Jwts.builder()

.addClaims(claims)//自定义信息(有效载荷)

.signWith(SignatureAlgorithm.HS256, signKey)//签名算法(头部)

.setExpiration(new Date(System.currentTimeMillis() + expire))//过期时间

.compact();

return jwt;

}

/**

* 解析JWT令牌

* @param jwt JWT令牌

* @return JWT第二部分负载 payload 中存储的内容

*/

public static Claims parseJWT(String jwt){

Claims claims = Jwts.parser()

.setSigningKey(signKey)//指定签名密钥

.parseClaimsJws(jwt)//指定令牌Token

.getBody();

return claims;

}

}


https://www.xamrdz.com/backend/3yy1941875.html

相关文章: