jwt如何加盐_JWT(JSON WEB TOKENS)的使用,无状态token机制

JWT(JSON Web Tokens)是一种无状态的身份验证机制,常用于实现单点登录。然而,JWT存在token泄露和无法续签的问题。JWT由header、payload和signature三部分组成,其中payload可包含用户信息。签名部分通过header和payload进行加密,确保安全性。文章还提供了一个简单的JWT生成和验证的Java代码示例。
摘要由CSDN通过智能技术生成

2ff34e647e2e3cdfd8dca593e17d9b0a.png

本文结束啦感谢您的阅读

JWT的优点

由于JWT本身是无状态的,仅仅是存储登录授权的信息,可以实现单点登录的功能,因为在多个系统中只要在实现jwt token的时候用同一个密钥进行加密,则可以实现跨平台而登陆。

JWT的缺点

==token泄露问题==:由于只要拿到token就可以在不同机器上进行登录,因此只要token泄露出去后用户可以通过登录后改变密码进行窃取。

==token续签问题==:jwt虽然内置了token过期的功能,但是并没有提供token续签的问题,如果用户在进行重要信息的存储时,刚好token过期了,则导致用户需要重新登录,因此容易造成重要信息丢失,影响客户体验。该项可以通过设计各种策略刷新token过期时间,而session这方面就比jwt好很多,session会自动刷新过期时间,例如是30min过期,但用户在30min内登录session后重新计算过期时间。

JWT token构成

一个token包含三个部分(Header,Payload,Signature)

header 头部

标头通常由两部分组成:令牌的类型,即JWT,以及哈希算法,如HMAC SHA256或RSA。1

2

3

4{

"alg": "HS256",

"typ": "JWT"

}

HS256 表示使用了 HMAC-SHA256 来生成签名。接下来对这部分内容使用 Base64Url编码组成了JWT结构的第一部分。

Payload 载荷

payload包含三种类型的claim:reserved, public 和 private1

2

3

4

5{

"sub": "1234567890",

"name": "John Doe",

"admin": true

}

Reserved claims: 这些claim是JWT预先定义的,在JWT中并不会强制使用它们,而是推荐使用,常用的有1

2

3

4

5

6

7iss: jwt签发者

sub: jwt所面向的用户

aud: 接收jwt的一方

exp: jwt的过期时间,这个过期时间必须要大于签发时间

nbf: 定义在什么时间之前,该jwt都是不可用的.

iat: jwt的签发时间

jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

Public claims:根据需要定义自己的字段,注意应该避免冲突

Private claims:这些是自定义的字段,可以用来在双方之间交换信息

上述的负载需要经过Base64Url编码后作为JWT结构的第二部分。

Signature 签名

jwt的第三部分是一个签证信息,这个签证信息算法如下:

base64UrlEncode(header) + "." + base64UrlEncode(payload)+your-256-bit-secret1

2

3

4HMACSHA256(

base64UrlEncode(header) + "." +

base64UrlEncode(payload),

secret)

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

JWT简单案例

引入依赖包1

2

3

4

5

com.auth0

java-jwt

3.4.0

案例代码1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135package jwt;

import com.auth0.jwt.JWT;

import com.auth0.jwt.JWTVerifier;

import com.auth0.jwt.algorithms.Algorithm;

import com.auth0.jwt.exceptions.TokenExpiredException;

import com.auth0.jwt.interfaces.Claim;

import com.auth0.jwt.interfaces.DecodedJWT;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import java.io.IOException;

import java.io.InputStream;

import java.util.*;

* JwtTokenUtil

*

* Description

*

* Creation Time: 2018910 0010 12:03.

*

* @author virvil

* @since jwtdemo 0.0.1

*/

public class{

* The constant logger.

*/

private static Logger logger = LoggerFactory.getLogger(JwtTokenUtil.class);

* The constant properties.

*/

private static Properties properties = new Properties();

* The constant signkey.

*/

private static String signkey = null;

* The constant algorithm.

*/

private static Algorithm algorithm = null;

/*

加载配置文件内容

*/

static {

InputStream inputStream = JwtTokenUtil.class.getClassLoader().getResourceAsStream("jwt.properties");

try {

properties.load(inputStream);

String signkey = properties.getProperty("signkey");

algorithm = Algorithm.HMAC256(signkey);

} catch (IOException e) {

logger.error("读取配置文件异常",e);

}

}

* Get token string.

*生成token

* @param username the username

* @return the string

*/

public static String getToken(String username){

Calendar calendar = Calendar.getInstance();

//签发时间

Date issueDate = calendar.getTime();

//过期时间

long expires = issueDate.getTime()+Integer.parseInt(properties.getProperty("timeout"));

Date expiresDate = new Date(expires);

//header

Map header = new HashMap<>();

header.put("alg","HS256");

header.put("typ","JWT");

String token = JWT.create()

.withHeader(header) //设置header头信息

.withClaim("iss","auth0") //设置payload

.withClaim("username",username)

.withIssuedAt(issueDate)

.withExpiresAt(expiresDate)

.sign(algorithm);

return token;

}

* Verify token map.

*对token进行解密

* @param token the token

* @return the map

*/

public static Map verifyToken(String token){

JWTVerifier jwtVerifier = JWT.require(algorithm).build();

DecodedJWT verify = null;

try {

verify = jwtVerifier.verify(token);

return verify.getClaims();

}catch (TokenExpiredException ex){

logger.error("token已经过期",ex);

}catch (Exception e){

logger.error("登录异常",e);

}

return null;

}

* The entry point of application.

*

* @param args the input arguments

*/

public static void main(String[] args){

String username = "virvil";

String token = getToken(username);

//验证token是否正确

Map claims = verifyToken(token);

if (claims!=null){

Claim usernameClaim = claims.get("username");

//此处获得的信息可以到数据库中进行查询,验证是否存在该用户信息,这里我只是简单测试,莫怪

System.out.println(username.equals(usernameClaim.asString())?"token验证成功":"token验证失败");

}

//用一个过期的token来验证结果

String token2 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +

".eyJpc3MiOiJhdXRoMCIsImV4cCI6MTUzNjU2MTUzNSwiaWF0IjoxNTM2NTYxNTM0LCJ1c2VybmFtZSI6InZpcnZpbCJ9" +

".JNNCERaaApOaoNYV45liZTJ-mF7UIRLNz-EY5tAPC4Q";

verifyToken(token2);

}

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值