分布式系统session一致性的解决方案

mac2026-08-18  2

遇到的问题

1.在分布式集群中,我们该如何确保每一次用户访问集群的session都是原来的session

解决方案

1.基于服务器端 (1)基于session stcikly:他可以在用户登录的时候,将这个session与集群的一台机器绑定起来,以后这个session的请求都会落到这台机器上面。 (2)将session复制到集群中的每一台机器上面 (3)使用缓存,例如redis等等保存session信息,每次拦截器里面都去redis里面检验一次 2.基于客户端 (1)就是session信息只保存在客户端里面,服务器端不保存,只做session的校验。

基于客户端使用JWT解决的方案

1.在这个过程中涉及到的一些概念 (1)token:返回给客户端,用于登录的凭证。

token=base64(header).base64(payload).sinature。

(2)header:组成token的一部分,同时用于定义签名sinature的生成算法

{ "alg": "HS256", "typ": "JWT" }

(3)payload:同样是token的组成的一部分,里面可以声明定义用户信息,过期信息等等

{ "sub": "1234567890", "name": "Michael", "admin": true, "exp": 1572687092123 }

(4)sinature:用来判断token里面的header和payload信息是否修改过,判断token是否过期等 (5)key:只是存在服务器端的密钥,用于拿来加密的,避免伪造token的,

2.生成token的过程: 我们是根据header,payload,key来生成token的 大致的过程如下: 最后代码实现如下:

package com.example.util; import com.alibaba.fastjson.JSON; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.apache.commons.codec.binary.Base64; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * @author zhouyongquan * @date 2019/11/2 下午4:28 * @description jwt的token的工具类 */ public class JwtTokenUtils { /** * 过期时间 */ public static final Integer TOKEN_EXPIRE_TIME = 3600 * 24 * 2; /** * 参与生成token的密钥key */ public static final String TOKEN_KEY = "MICHAEL1994"; /** * 主函数 * * @param args */ public static void main(String[] args) { //测试生成token String token = generateToken("michael"); System.out.println(token); //解析生成的token Claims claims = pharseToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6Im1pY2hhZWwiLCJleHAiOjE1NzI2ODY0NTE3ODN9.hLpsCqO3Vq967SV_6cc9LXgZI8Pg7eZMrNFOvL25GWc"); System.out.println(claims); } /** * 由token和密钥获取header,payload里面的信息 * * @param token * @param secretkey * @return */ public static Claims pharseToken(String token, String secretkey) { Jws<Claims> claimsJwt = Jwts.parser() .setSigningKey(secretkey) .parseClaimsJws(token); return claimsJwt.getBody(); } /** * 由token获取header,payload里面的信息 * * @param token * @return */ public static Claims pharseToken(String token) { Jws<Claims> claimsJwt = Jwts.parser() .setSigningKey(generatorSecretkey(TOKEN_KEY)) .parseClaimsJws(token); return claimsJwt.getBody(); } /** * 传入header,payload,secretkey生成token * * @param header * @param payload * @param secretkey * @return */ public static String generateToken(Map<String, Object> header, Map<String, Object> payload, String secretkey) { String token = Jwts.builder() .setHeader(header) .setPayload(JSON.toJSONString(payload)) .signWith(SignatureAlgorithm.HS256, secretkey).compact(); return token; } /** * 添加一些默认信息生成token * * @param userName * @param exp * @param secretkey * @return */ public static String generateToken(String userName, long exp, String secretkey) { Map<String, Object> defaultHeader = new HashMap<>(); defaultHeader.put("alg", "HS256"); defaultHeader.put("typ", "JWT"); Map<String, Object> payload = new HashMap<>(); payload.put("userName", userName); payload.put("exp", exp); return generateToken(defaultHeader, payload, secretkey); } /** * userName,secretkey生成token * * @param userName * @param secretkey * @return */ public static String generateToken(String userName, String secretkey) { return generateToken(userName, getDefaultTokenExpireTime(), secretkey); } /** * 使用默认密钥生成token * * @param userName * @return */ public static String generateToken(String userName) { return generateToken(userName, generatorSecretkey(TOKEN_KEY)); } /** * 计算过期时间 * * @return */ public static Long getDefaultTokenExpireTime() { Date curDate = new Date(); return curDate.getTime() + TOKEN_EXPIRE_TIME; } /** * 加密 * * @param key * @return */ private static String generatorSecretkey(String key) { return Base64.encodeBase64String(key.getBytes()); } }
最新回复(0)