一、会话跟踪
1 什么是会话什么是请求?
会话:浏览器与服务器之间的一次连接
请求:前端发送的指令
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public ResultData login(@RequestBody Emp emp){
Emp e = empService.getByUsernameByPassword(emp.getUsername(),emp.getPassword());
return e != null ? ResultData.success(e) : ResultData.error();
}
}
2 什么是会话跟踪技术?
使用会话跟踪技术就是要完成在同一个会话中,多个请求之间进行共享数据。
3 会话跟踪技术包括?
Cookie(浏览器) ,Session(服务器), 令牌(JWT)
① Cookie
I cookie执行流程:
II Cookie 快速入门:
a. 设置cookie。有响应对象操作
传递参数 HttpServletResponse
设置cookie, 传一个键值对
设置最大存货时间
添加cookie
带到客户端
// 设置cookie
@GetMapping("/setc")
public ResultData setc(HttpServletResponse response){
// 设置cookie, 传一个键值对
Cookie cookie = new Cookie("username","lss");
// 设置最大存货时间 单位为秒
cookie.setMaxAge(3600);
// 添加cookie
response.addCookie(cookie);
return ResultData.success();
}
II 获取cookie
传递参数:HttpServletResponse,HttpSession
删除原有session -- session.invalidate();
获取当前服务器中所有存在的自己的cookie
合理化校验
遍历判断要获取的cookie存不存在 用key去判断
// 获取cookie
@GetMapping("/getc")
public ResultData getc(HttpServletRequest request, HttpSession session){
// 删除原有session
session.invalidate();
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0){
for (Cookie cookie : cookies) {
if ("username".equals(cookie.getName())){
System.out.println(cookie.getValue());
}
}
}
return ResultData.success();
}
③ Session(服务器端会话跟踪技术):
1 服务器创建(服务器中有session池)执行流程:
2 Session快速入门
I 设置session
传递参数 HttpSession
放数据
返回去
// 设置session
@GetMapping("/sets")
public ResultData sets(HttpSession session){
session.setAttribute("username","张三");
return ResultData.success();
}
II 获取Session
传递参数 HttpServletRequest
获得session
存放对象(要强转)
返回去
// 获取session
@GetMapping("/gets")
public ResultData gets(HttpServletRequest request){
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
return ResultData.success(username);
}
④ 令牌技术
1 jwt 令牌技术
简介:一个简洁的、 自包含的格式
组成:(JWT令牌由三个部分组成,三个部分之间使用英文的点来分割)
-
第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{"alg":"HS256","type":"JWT"}
-
第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{"id":"1","username":"Tom"}
-
第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来。
2 jwt 使用:
I 引入依赖
<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
II 创建jwt
jwt是个接口,实体类过于复杂,使用工厂设计模式(工具类带s的)
创建map,添加jwt要传的内容 -- 载体对象(Claims)
生成jwt:声明 jwt 添加荷载部分,添加头部信息 算法和密钥, 添加有效期,最后构建密钥
@Test
public void CreateJWT(){
JwtBuilder builder = Jwts.builder();
Map<String,Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("username","tom");
String jwt = builder.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, "wolfcode")
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 3))
.compact();
System.out.println(jwt);
}
III 解析令牌:
指定密钥
提供一大堆jwt
@Test
public void parseJwt(){
JwtParser jwt = Jwts.parser().setSigningKey("wolfcode");
Claims claims = jwt.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJ0b20iLCJleHAiOjE3MjA1MjU0MjF9.AhuZUWrm5IwMioERz5FHw4fgXnfq_hnOcK89pI-4L0g").getBody();
System.out.println(claims);
}
IV 封装工具类
封装字段:
签名密钥
有效时间
private String signingKey;
private String expiration;
封装方法:
生成JWT令牌
public static String createJwt(Map<String,Object> claims){
JwtBuilder builder = Jwts.builder();
String jwt = builder.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signingKey)
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.compact();
return jwt;
}
解析JWT令牌
public static Claims parseJwt(String claims){
Claims jwt = Jwts.parser()
.setSigningKey(signingKey)
.parseClaimsJws(claims)
.getBody();
return jwt;
}
V 更改控制层
判断登录是否成功
若失败返回错位信息
定义载体信息,把查到的值传进去
调用工具类生成令牌,将map塞进去
返回数据
@PostMapping("/login")
public ResultData login(@RequestBody Emp emp){
Emp e = empService.getByUsernameByPassword(emp.getUsername(),emp.getPassword());
if (e == null){
return ResultData.error("用户名失败");
}
Map<String, Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("username","张三");
String jwt = JWTUtils.createJwt(claims);
return ResultData.success(jwt);
}