单点登录(SSO)—微服务之间的session共享
应用:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的系统
一:同域名下SSO
可以使用Cookie-Session机制
-
cookie共享:由于cookie不能跨域,需要将Cookie的域设置为顶域
-
session共享:使用SpringSession或redis解决
例如:系统app1(app1.a.com)、系统app2(app2.a.com)、登录系统sso(sso.a.com)
sso登录后,设置cookie的域为.a.com
二:不同域名下SSO
背景:手机app没有cookie,微服务广泛使用
使用JWT认证(json web token)
概念:请求头携带jwt数据,服务器不记录信息(无状态)
使用流程:
1.客户端发送登录信息过来
2.登录服务系统访问数据库验证信息
3.登录服务系统生成jwt,以字符串token响应给客户端
4.客户端把jwt存在threadlocal中,每次请求放在head中
5.其他系统从head中截取jwt,验证信息
注意:jwt签发和解析都需要传入同一个密钥,用于解析时判断jwt数据是否被修改 (单点登录关键)
springboot中编写工具类:
package com.supergo.sso.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
@ConfigurationProperties("jwt.config")
@Component
public class JwtUtil {
private String key; //密钥
private long ttl; //过期时间
/**
* 生成JWT token
* @param id 可以放用户id
* @param subject 用户名
* @param role 自定义字段,例如:解析时,“admin”判断为管理员,“user”判断为用户
* @return
*/
public String createToken(String id,String subject,String role){
JwtBuilder builder= Jwts.builder()
.setId(id)
.setSubject(subject)
.setIssuedAt(new Date()) //签发时间
.claim("role",role) //自定义字段,可以写多个claim
.signWith(SignatureAlgorithm.HS256,key); //编码和密钥
if (ttl>0){
builder.setExpiration(new Date(System.currentTimeMillis()+ttl*1000));//过期时间
}
return builder.compact();
}
/**
* JWT token解析
* @param token
* @return map类型,存放的是jwt的body部分
*/
public Claims parseToken(String token){
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token)
.getBody();
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getTtl() {
return ttl;
}
public void setTtl(long ttl) {
this.ttl = ttl;
}
}