一.状态
先从状态说起,http无状态
我们知道,HTTP 是无状态的。也就是说,HTTP 请求方和响应方间无法维护状态,都是一次性它不知道前后的请求都发生了什么的,每一次请求都是独立的,下一次请求并不会携带上一次请求的数据。
但是有的场景,我们需要维护状态,就比如说一个用户登录想访问其他资源就必须是在登录的状态下进行访问,评论、关注等
那怎么办,我们是不是需要一个标记对不对!
二.登录校验
三.会话技术
1.会话:
用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应
2.会话跟踪
一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。
3.会话跟踪技术方案
- 客户端会话跟踪技术:Cookie
- 服务端会话跟踪技术:Session
- 令牌技术
4.Cookie
4.1 举例:
@Slf4j
@RestController
public class sessionController{
//设置Cookie
@GetMapping("/c1")
public Result cookiel(HttpServletResponse response){
response.addCookie(new Cookie( name: "login username",value:"itheima"));
return Result.success();
}
//获取Cookie
@GetMapping("/c2")
public Result cookie2(HttpServletRequest request){
Cookie[]cookies=request.getCookies();
//获取所有的Cookie
for(Cookie cookie:cookies){
if(cookie.getName().equals("login username")){//输出name为 login username 的cookie
System.out.println("login username: "+cookie.getValue());
}
}
return Result.success();
}
4.2 测试
此时看到服务端返回的Set-Cookie,然后保存在浏览器
再访问c2接口,看看是否把cookie携带到服务端
4.3 总结
5.Session(基于cookie)
第一次访问时,服务端会生成会话seesion对象并存储,对应一个sessionId,并通过http的响应头自动返回,值在Set-cookie里面,
5.1 举例
5.2 测试
首先看到是响应回来的Set-cookie,也就是id
可以看到cookie里面又多了一个sessionID
然后再访问s2接口
5.3 总结
6.令牌技术
本质其实就是一个字符串,常见的令牌技术有很多,例如JWT、OTP、ORTOken、OAuth令牌等
以JWT为例进行讲解
6.1 JWT(JSON Web Token)
- 定义了一种简洁的、自包含的格式,用于在通信双方以ison数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的.
组成:
- 第一部分:Header(头),记录令牌类型、签名算法等。例如:{alg":"HS256","type":"JWT”}
- 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。例如:{"id":"1","username":"Tom")
- 第三部分:signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。
例如那么是如何将上面的json数据变成底下的字符串的呢?其实是进行了编码-Base64 编码
需要注意的是第三部分:
数字签名部分不是直接对头部和载荷的Base64URL编码结果进行加密,而是先对头部和载荷的Base64URL编码字符串用”.”(点)连接起来,然后使用头部中指定的签名算法和密钥对这个连接后的字符串进行加密。加密后的结果再进行Base64URL编码,得到最终的签名部分。
其实就是两个步骤:
- 登录生成令牌
- 后续请求校验令牌
6.2 生成JWT
1.引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.生成
public void testGeniwt(){
Map<sString,object>claims =new HashMap<>();
claims.put("id",1);
claims.put("name","tom");
String jwt = Jwts.builder().signwith(SiqnatureAlgorithm.Hs256,"itheima").setclaims(claims)
.setExpiration(new Date(system.currentTimeMillis()+ 3600*1000)).compact();
System.out.println(jwt);
}
3.解析