一、单点登录概述
单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。不同于传统的单体应用,所有业务都在一个应用中,在分布式服务中,会有很多独立的项目,而这些项目又是有联系的,如A项目为购物车模块,B项目为订单模块,当我在向购物车加入商品的时候需要登录,而当我查询订单的时候也需要登录,那单点登录就是如果我登陆了购物车应用或者订单应用其中之一,再登陆其他的应用时便不需要登录。
如百度的新闻和百度贴吧。
二、实现方式
session广播方式
这种方式在少量应用的情况下是可以的,但是如果累计有几十个应用的话,每个应用都持有一份相同的session,这样就造成了内存资源的浪费,降低性能。
cookie+redis
这种方式当用户成功以后,生成一个唯一id值,然后将这个值和用户的信息存入到redis中,也可以设置过期时间,然后再通过cookie的方式将这个id推送给浏览器,这样当浏览器再访问其他需要登录的功能时就检查有没有该cookie,这种方式不用每个服务器都保存一份,减少了内存的消耗。
token方式
这种方式在用户登录成功以后以某种规则将用户的信息进行加密,然后通过拼接url的方式返回。
jwt介绍
刚才说了,用户登录成功以后以某种规则将用户的信息进行加密,然后通过拼接url的方式返回,那jwt就是一种处理该字符串的一种规则。jwt包含三部分,第一部分是头信息,主要为token的类型和使用的加密算法,第二部分为有效载荷,也就是用户的信息,第三部分为签名,可以防止内容被窜改。
jwt具体实现
引入依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
JWT工具类:
public class JwtUtils {
public static final long EXPIRE = 1000 * 60 * 60 * 24; //token过期时间
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; //秘钥
//生成token字符串的方法
public static String getJwtToken(String id, String nickname){
String JwtToken = Jwts.builder()
.setHeaderParam("typ", "JWT") //设置jwt头信息
.setHeaderParam("alg", "HS256")
.setSubject("user")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) //设置过期时间
.claim("id", id) //设置token主体部分 ,存储用户信息
.claim("nickname", nickname)
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
.compact();
return JwtToken;
}
/**
* 判断token是否存在与有效
* @param jwtToken
* @return
*/
public static boolean checkToken(String jwtToken) {
if(StringUtils.isEmpty(jwtToken)) return false;
try {
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 判断token是否存在与有效
* @param request
* @return
*/
public static boolean checkToken(HttpServletRequest request) {
try {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken)) return false;
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据token字符串获取会员id
* @param request
* @return
*/
public static String getMemberIdByJwtToken(HttpServletRequest request) {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
Claims claims = claimsJws.getBody();
return (String)claims.get("id");
}
}
调用生成token方法查看控制台
这就是JWT规则给我们生成的token。