利用token进行用户登录的流程:
1.首先客户端使用用户名和密码请求登录
2.服务端收到请求,验证用户名和密码
3.验证成功后,客户端会给客户端返回一个token,客户端会将token存储起来
4.之后的每次向服务器请求资源时,都会带着这个token值
5.服务端收到请求后,会去验证客户端请求里面带着的token,验证成功后,服务端就会给客户端返回请求数据
关于Session与Token的区别:Session默认是保存在服务器的内存中的数据,会占用一定的服务器内存资源,并且,不适合集群或分布式系统(虽然可以通过共享Session来解决),客户携带的Session ID只具有唯一性的特点(理论上),不具备数据含义……而Token的本质是将有意义的数据进行加密处理后的结果,各服务器都只需要具有解析这个加密数据的功能即可获取到其中的信息含义,理论上不占用内存资源,更适用于集群和分布式系统,但是,存在一定的被解密的风险(概率极低)。
所以在此处我们推荐用JWT token的方式进行用户认证.
什么时JWT?
JWT就是token的一种具体实现方式,其全称是JSON Web Token
JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。
一个原始的JWT数据应该包含3个部分:
HEADER:ALGORITHM & TOKEN TYPE(算法与Token类型)
{
"alg": "HS256",
"typ": "JWT"
}
PAYLOAD(载荷):DATA
此部分的数据是自定义的,可按需存入任何所需的数据。
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
VERIFY SIGNATURE(验证签名)
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
下面说一下项目里的JWT具体要如何操作
在使用JWT之前,需要在项目中添加相关的依赖,用于生成JWT和解析JWT,例如添加:
<!-- JJWT(Java JWT) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
紧接着在test包下创建测试类,这里是生成jjwt数据
public class JwtTests {
// Secret Key
String secretKey = "97iuFDVDfv97iuk534Tht3KJR89kBGFSBgfds";
@Test
public void testGenerate() {
// 准备Claims值
Map<String, Object> claims = new HashMap<>();
claims.put("id", 9527);
claims.put("name", "LiuLaoShi");
claims.put("nickname", "JavaCangLaoShi");
// JWT的过期时间
Date expiration = new Date(System.currentTimeMillis() + 5 * 60 * 1000);
System.out.println("过期时间:" + expiration);
// JWT的组成:Header(头:算法和Token类型)、Payload(载荷)、Signature(签名)
String jwt = Jwts.builder()
// Header
.setHeaderParam("alg", "HS256")
.setHeaderParam("typ", "JWT")
// Payload
.setClaims(claims)
.setExpiration(expiration)
// Signature
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
System.out.println("JWT=" + jwt);
这里是解析jwt数据
@Test
public void testParse() {
// 注意:必须使用相同secretKey生成的JWT,否则会解析失败
// 注意:不可以使用过期的JWT,否则会解析失败
// 注意:复制粘贴此JWT时,不要带“尾巴”,否则会解析失败
// 注意:不可以恶意修改JWT中的任何字符,否则会解析失败
String jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiTGl1TGFvU2hpIiwibmlja25hbWUiOiJKYXZhQ2FuZ0xhb1NoaSIsImlkIjo5NTI3LCJleHAiOjE2NjI0NTY3ODN9.32MwkSbDz1ce4EvEKHFMCIjcQFUDZz6hn5MtAYr0njQ";
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
Integer id = claims.get("id", Integer.class);
String name = claims.get("name", String.class);
String nickname = claims.get("nickname", String.class);
System.out.println("id = " + id);
System.out.println("name = " + name);
System.out.println("nickname = " + nickname);
}