SSO方式实现微服务的登入业务

本文介绍了在分布式环境中实现登录的两种方式:单点登录(SSO)和使用JWT(JSON Web Tokens)。详细讲解了session复制和session+redis方案的优缺点,并重点阐述了JWT的工作原理、组成部分及优点。提供了JWT的Java实现示例,包括创建和验证JWT Token的方法。
摘要由CSDN通过智能技术生成
1.登录业务介绍:
单一服务器模式
单一服务器模式用于登录的方式通常是使用session。
1.微服务

在分布式中通常使用单点登入(SSO(single sign on)模式)的方式实现用户登入,三种实现方式

1.1 session广播机制实现

在分布式中各个服务器都是独立运行,互不干涉,如果只是使用单个session的话那么每次打开一个服务器都需要重新输入信息登入,但是可以通过复制session的方式实现输入一次信息就可以登入多个服务器,但是缺点也很明显,服务器少还可以,如果服务器多,复制的session也就多,占用进程和浪费空间。以前使用,现在不推荐。

1.2 使用session+redis实现

实现过程:

当你在项目的任意模块登入时,数据将存储在两个地方

  1. redis:key: 生成唯一随机值 value:用户数据
  2. cookie:把redis生成的key放到cookie中

访问其他模块时,发送请求带着cookie进行发送,通过request获取cookie,再把获取的cookie到redis中进行查询即可。

1.3 使用令牌(token)

解释:通过一定的规则生成包含用户信息的字符串

实现过程:

  1. 当你在项目的任意模块登入后,生成相应的token,并返回
    • 通过cookie返回
    • 通过地址栏返回
  2. 每次访问其他模块时都会携带token,根据这个token获取用户信息,有则登入。

规则可以自定义也可以使用已封装好的,eg:JWT,HMAC(AK/SK)

2. JWT
2.1 什么是JWT?

JSON Web Tokens, 这是一个开放的标准,规定了一种Token实现方式,以JSON为格式.

2.2 JWT的组成
2.2.1 JWT头

描述JWT元数据的JSON对象,使用Base64 URL转换为字符串保存。

alg------》alg属性表示签名使用的算法

typ------》typ属性表示令牌的类型

{
  "alg": "HS256",  
  "typ": "JWT"     
}
2.2.2 有效载荷

WT的主体内容部分,JSON对象,包含需要传递的数据,使用Base64 URL转换为字符串保存。

默认字段:

sub:JWT所面向的用户
iss:JWT的签发者
iat(issued at): 在什么时候签发的token
exp(expires): token什么时候过期
nbf(not before):token在此时间之前不能被接收处理
jti:JWT ID为web token提供唯一标识

自定义字段:不建议存放密码

{
    "name":"xioaxian" 
}

注:Base64是一种编码不是一种加密过程

2.2.3 数字签名

再给上述拼接成的字符串进行加密之前,要在末尾加上数字签名,而签名的作用是防止抵赖以及防止数据被修改。数字签名则是使用密钥(secret)也可以叫私钥,这个密钥每个公司都有自己的生成方法,最后用HS256进行加密。

2.2.4 JWT的优点

通用:因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。

紧凑:JWT的构成非常简单,字节占用很小,可以通过 GET、POST 等放在 HTTP 的 header 中,非常便于传输。

扩展:JWT是自我包涵的,包含了必要的所有信息,不需要在服务端保存会话信息, 非常易于应用的扩展。

2.3 怎么使用JWT
2.2.1导入依赖
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>
2.2.2 创建工具类
public class JwtUtils {

//------------------------------------常量------------------------------------------------ 
/*
    EXPIRE     :令牌失效时间  (1000 * 60 * 60 * 24)ms  24h     
    APP_SECRET :密钥,【自定义】
*/
    public static final long EXPIRE = 1000 * 60 * 60 * 24;
    public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO";

//------------------------------------常量------------------------------------------------
    
//-----------------------------------获取token--------------------------------------------
    
    public static String getJwtToken(String id, String name){
   
        String JwtToken = Jwts.builder()
                .setHeaderParam("typ", "JWT")      //令牌的类型
                .setHeaderParam("alg", "HS256")    //加密算法
                .setSubject("user")                //分类,【根据实际修改】
                .setIssuedAt(new Date())           //生成token日期
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                .claim("id", id)                   //【自定义字段】
                .claim("name", name)
                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();

        return JwtToken;
    }
//-------------------------------判断token是否存在与有效,传jwtToken-------------------------

    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是否存在与有效,传request--------------------------

    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;
    }
//---------------------------------获取id-------------------------------------------------
 
    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");
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B64A-消闲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值