Cookies是会话跟踪技术的一种,通过将数据保存到客户端的浏览器上以此来达到会话间共享数据的效果。
从打开浏览器开始访问页面直到关闭浏览器断开连接算作一次会话(Session),一次会话中可以包含多次请求-响应。每次的请求响应都是无状态的,意味着服务器不能通过这一次请求得道上一次请求发生了什么。
优点:HTTP协议默认支持
缺点:1.不能进行跨域 2.Cookies始终为不安全的数据,用户可以禁用Cookies 3.移动端不可用
跨域:域名、IP、端口号只要有一个不同的链接就算跨域。
通过HttpServletResponse、HttpServletRequest获取响应/请求信息,在响应信息中设立cookies,在请求信息中获取浏览器所有的cookies。
@RestController
public class SessionController {
@GetMapping("/setCookies")
public String setCookies(HttpServletResponse response){
response.addCookie(new Cookie("name","yi"));
return "ok";
}
@GetMapping("/getCookies")
public String getCookies(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
for(Cookie cookie:cookies){
System.out.println(cookie.getName()+":"+cookie.getValue());
}
return "ok";
}
}
Session是基于Cookies实现的,也是一种会话追踪技术。
Session与Cookies的不同在于Session是将信息存储在服务器上形成Session对象而不是浏览器中。
浏览器向服务器发送第一次请求时,服务器会生成一个独一无二的Session对象,并将Session对象的ID通过设置Cookies的方式响应给浏览器,这样下一次浏览器请求时便会携带含有SessionID的cookies信息。
浏览器进行第二次请求时,服务器通过请求中携带的SessionID就可以找到相对应的Session对象,从而得知这次会话中存储了什么信息。
优点:存储在服务端,数据较为安全
缺点:1.服务器集群下无法使用, 2.基于Cookies所以含有Cookies所有的缺点。
当参数为HttpSession时,程序会自动判断当前请求是否有对应的会话对象,如果没有则新建一个HttpSession对象,并在响应头中加入set-cookies:SessionId…
getSession与getSession2等价,可以从HttpServletRequest中获取Session对象。
@GetMapping("/setSession")
public String setSession(HttpSession session){
System.out.println(session.hashCode());
session.setAttribute("name","li");
return "OK";
}
@GetMapping("/getSession")
public String getSession(HttpSession session){
System.out.println(session.hashCode());
System.out.println(session.getAttribute("name"));
return "OK";
}
@GetMapping("/getSession2")
public String getSession2(HttpServletRequest request){
HttpSession session = request.getSession();
System.out.println(session.hashCode());
System.out.println(session.getAttribute("name"));
return "OK";
}
客户端浏览器在第一次请求时(如登录成功),服务器生成一个令牌(一个字符串),通过响应返回给浏览器。浏览器可以将收到的令牌存储在任何位置。
在之后的每一次请求中携带该令牌,服务器会对请求中的令牌进行校验,从而返回对应的结果。
第一部分:Header(头),记录令牌类型、签名算法
第二部分:Payload(有效载荷),携带自定义信息。里面的消息术语称为Claims
第三部分:Signature(签名),融合header、payload并加入指定秘钥,通过签名算法计算而来
优点:支持PC移动端、解决集群环境认证问题、减轻服务端存储压力、
缺点:需要自己实现
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-gson</artifactId>
<version>0.11.2</version>
</dependency>
//随便写的秘钥
String secret="4wAJAxLrSdtgJC8G2jsC/IcJMPfAp+a3IHJBYZkufYCQdh2Afk1TeHRgSwX/fEXHBGaP8mftoUiSd22G93GJ5A==";
//生成JWT String,通过claims参数传入有效载荷
public String GenJWT(Map<String,Object> claims){
String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, secret)//签名算法秘钥
.setClaims(claims)//指定有效载荷(自定义数据)
.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//1小时过期
.compact();
return jwt;
}
public void ParseJWT(String jwt) {
try {
Claims body = Jwts.parser()
.setSigningKey(secret) //设置秘钥
.parseClaimsJws(jwt) //填写要解析的jwt
.getBody(); //获得自定义数据
System.out.println(body);
System.out.println("解析成功");
} catch (Exception e){
System.out.println("解析失败,被篡改");
}
}
@Test
public void testJWT() throws InterruptedException {
HashMap<String, Object> claims = new HashMap<>();
claims.put("name","li");
String jwt= GenJWT(claims);
System.out.println(jwt);
ParseJWT(jwt);
}