会话技术
一次会话包括若干次连接,一次连接即一次请求和响应。
1. Cookie
优点:HTTP协议自有的技术,嵌入在请求头(键cookie)和响应头(键set-cookie)中,所有的键值对都存储在浏览器端。
缺点:
a. 移动端app无法使用cookie
b. 不安全,用户可以自行禁止cookie,这样就无法使用cookie保持会话了
c. cookie不能在跨域的场合中使用
示例代码:
import edu.recipePost.pojo.Result;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class SessionController {
// 设置cookie
@GetMapping("/get-cookie")
public Result getCookie(HttpServletResponse response) { // 从HttpServletResponse获取响应头
Cookie cookie = new Cookie("cookie_key_name", "value"); // 创建cookie
cookie.setMaxAge(3600*24*7); //cookie设置生命周期,单位是秒
cookie.setPath("/cookie/age"); //cookie设置路径
response.addCookie(cookie); //response对象添加cookie
return Result.success();
}
// 获取cookie
@GetMapping("/other")
public Result setCookie(HttpServletRequest request) { // 从HttpServletRequest获取请求头
Cookie[] cookies = request.getCookies(); //获取cookie对象
for (Cookie cookie:cookies) {
if(cookie.getName().equals("cookie_key_name")) {
log.info("cookie_key_name:"+cookie.getValue()); // 数值cookie对应的键值
}
}
return Result.success();
}
}
2. Session
概述:浏览器的cookie中存储SessionID,请求头的cookie和响应头的set-cookie传输的都是SessionID,所有的键值对都存储在服务器端,服务器通过浏览器传来的SessionID来找到Session对象,Session对象中存储有一次会话的键值对。
优点:数据(键值对)存储在服务器端,比较安全
缺点:
a. 目前大型项目都是服务器集群,服务器集群环境下无法直接使用Session。原因:两次访问会负载均衡到不同的服务器,导致Session对象分布在各个服务器,各服务器之间的Session对象不同步。
b. Session技术依靠HTTP协议的Cookie实现,所以Cookie的缺点也是Session的缺点。
与Cookie区别:
a. Cookie技术键值对存储在浏览器,Session技术键值对存储在服务器;
b. Session技术浏览器的cookie里只存有SessionID,通过SessionID请求服务器,找到服务器的Session对象,从而找到此次会话的键值对。
示例代码:
import edu.recipePost.pojo.Result;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class SessionController {
// 第一次访问时,往HttpSession存储值
@GetMapping("/set-session")
public Result getSession(HttpSession session) { // 获取会话对象session,若不存在则创建session;存在就获取当前请求对应的session
log.info("HttpSession-test1: "+session.hashCode()); // 同次会话HttpSession-test1: 1675666366
session.setAttribute("loginUser", "tom"); // session存值
return Result.success();
}
// 从HttpSession获取值
@GetMapping("/get-session")
public Result setCookie(HttpServletRequest request) { // 通过请求头获取会话对象,也可以通过HttpSession获取会话对象
HttpSession session = request.getSession(); // 通过请求头获取会话对象
log.info("HttpSession-test2: "+session.hashCode()); // 同次会话HttpSession-test1: 1675666366
Object loginUser = session.getAttribute("loginUser");
log.info("loginUser: "+loginUser); // loginUser: tom
return Result.success(loginUser);
}
}
3. JWT令牌
JSON Web Token

结构:
由“.”分成三部分:
第一部分:描述令牌类型、签名算法的Header => 经过JSON封装 => 经过base64编码
第二部分:自定义信息和默认信息的Payload(有效载荷) => 经过JSON封装 => 经过base64编码
第三部分:数字签名,前两部分和指定密钥经过签名算法得到。防止被篡改。
相比于Cookie和Session,有以下优点:
a. 不仅支持Web,还支持PC端、移动端
b. 解决集群服务器环境下的认证问题
c. 减轻服务器端的存储压力
缺点:非HTTP协议天然生成,需要自己实现令牌的生成、存储与传输
Maven依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version></version>
</dependency>
实例代码:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import java.util.Date;
import java.util.Map;
public class JWTUtils {
@Value("${JWT.web.login.sign-key}")
private static String signKey;
@Value("${JWT.web.login.expire}")
private static Long expire;
public static String generateJWT(Map<String, Object> claims) {
return Jwts.builder()
.addClaims(claims) // 添加JSON实体数据
.signWith(SignatureAlgorithm.HS256, signKey) // 签名算法,签名密钥
.setExpiration(new Date(System.currentTimeMillis()+expire)) // token过期时间
.compact();
}
public static Claims parseJWT(String jwt) {
return Jwts.parser() // JWT解析器
.setSigningKey(signKey) // 添加签名密钥
.parseClaimsJws(jwt) // 解析JWT令牌
.getBody();
}
}