Token验证学习笔记

一、 对Token的认识

我们都知道HTTP协议是无状态的,这种无状态意味着程序需要验证每一步请求,从而辨别客户端的身份。

这种方式一般我们都是通过存储Session来完成。

基于服务器验证方式暴露的问题:

1. Session:每次认证用户发起请求时,服务器需要去创建一条记录来存储信息。在请求用户增加时,内存的开销也会不断增加。

2. 可扩展性:在服务端内存中使用Session存储登录信息,伴随着可扩展性的问题。

3. CORS(跨域资源共享):跨域资源的共享存在问题,在使用Ajax抓取另一个域的资源会出现禁止请求的情况。

4. CSRF(跨站请求伪造):用户在访问银行网站时,很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。

在这些问题中,可扩展性是最突出的。

Token的使用的特点:

1. 支持跨域访问

2. 无状态:Token机制在服务端不需要存储session信息,token自身包含了登录用户的信息,只需要在客户端的Cookie或本地介质存储信息。

扫描二维码关注公众号,回复: 11117655 查看本文章

3. 更适合CDN:可以通过内容分发网络请求服务端的所有资料,服务端提供API即可。

4. 去耦:不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成。

5. CSRF:跨站请求伪造的问题得以防范。

6. 性能提升

7. 基于标准化:API可以采用标准的JWT(JSON Web Token)。

二、 基于JWT的Token认证机制的实现

1. 一个JWT实际上就是一个字符串,它由三部分组成:头部、载荷和签名。

头部(Header)

JWT的头部承载两部分信息:

① 声明类型,这里是JWT

② 声明加密的算法,通常直接使用HAMC SHA256

{
    'type':'JWT',
    'alg':'HS256'
}

载荷(Payload)

① 标准中注册的声明

② 公共的声明

③ 私有的声明

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

① iss:JWT签发者

② sub:JWT所面向的用户

③ aud:接收JWT的一方

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

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

⑥ iat:JWT的签发时间

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

示例:

{
    "name":"zwz",
    "age":"18"
}

签名(Signature)

JWT的第三部分是一个签证信息:

① header(base64后的)

② payload(base64后的)

③ secret

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

密钥secret是保存在服务端的,服务端会根据这个密钥进行生成token和验证,所以需要保护好。

三、 Java方式实现

1. Maven依赖的添加

<dependency>
	<groupId>com.auth0</groupId>
	<artifactId>java-jwt</artifactId>
	<version>3.1.0</version>
</dependency>

加密代码:

public class JwtToken {
	public static String createToken() throws Exception{
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("alg", "HS256");
		map.put("typ", "JWT");
		String token = JWT.create()
				.withHeader(map)//header
				.withClaim("name", "zwz")//payload
				.withClaim("age", "18")
				.sign(Algorithm.HMAC256("secret"));//加密
		return token;
	}
}

验证代码:

public static void verifyToken(String token,String key) throws Exception{
		JWTVerifier verifier = JWT.require(Algorithm.HMAC256(key))
		        .build(); 
		    DecodedJWT jwt = verifier.verify(token);
		    Map<String, Claim> claims = jwt.getClaims();
		    System.out.println(claims.get("name").asString());
	}

payload部分,JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
发布了13 篇原创文章 · 获赞 1 · 访问量 8236

猜你喜欢

转载自blog.csdn.net/romanticRose/article/details/78135261
今日推荐