自学内容网 自学内容网

统一认证服务升级

现状

项目概述

1.后端认证服务

提供注册/登录/用户信息管理

提供Token管理

2.前端登录-sdk

提供统一登录弹窗SDK

现有认证流程

在这里插入图片描述

登录SDK详解

  1. 登录项目提供了统一登录的login.js,其功能是提供统一的登录页面,封装回调函数(如点击事件回调,登录成功回调)
  2. 业务前端项目编写登录模块,创建登录弹窗容器,拉起login.js,实现回调函数业务逻辑,实际就是将login.js嵌入到了业务前端项目,本质就是一个项目内的逻辑交互
现有Token机制

生成Token

// 签名秘钥
String secret = "secret";
// 令牌附属信息
LoginTokenBo audience = new LoginTokenBo();
audience.setUserId(userBodyBo.getUserId());
audience.setTerminal(terminal.getValue());
long currentTimeMillis = System.currentTimeMillis();
audience.setStamp(currentTimeMillis);
// 令牌
String token = JWTUtil.newToken(secret, JSON.toJSONString(audience));
if (StringUtils.isBlank(token)) {
    // 生成令牌出错
    return StringUtils.EMPTY;
}

// 将令牌写入到 Cookie(有效期:7 天)
final int expiry = 604800;
// 经令牌写入到 Redis
redisHelper.get(RedisDBIndexEnum.IDX36).setex(jointLoginTokenKey(userBodyBo.getUserId(), terminal), expiry, token);

验证Token

public int getLoginUserId(HttpServletRequest request) {
    int userId = 0;
    String token = getLoginCookieValue(request);
    if (StringUtils.isNotBlank(token)) {
        userId = getUserIdByNewCookie(token);
    }

    return userId;
}

销毁Token

public boolean  removeLoginState(HttpServletRequest request, HttpServletResponse response) {
    AtomicBoolean result = new AtomicBoolean(false);

    // 从新 Cookie 中获取用户信息,移除其登录状态
    String token = getLoginCookieValue(request);
    if (StringUtils.isNotBlank(token)) {
        extractLoginTokenAudienceBo(token).ifPresent(bo -> {
            int userId = getUserIdByNewCookie(token);
            if (userId > 0) {
                // 删除 Cookie
                CookieUtil.setCookie(response, GeneralFields.LOGIN_COOKIE, StringUtils.EMPTY,
                        GeneralFields.COOKIE_DOMAIN, 0, true);

                // 删除 redis 上存储的登录授权令牌
                GeneralTerminalEnum terminal = GeneralTerminalEnum.getByValue(bo.getTerminal()).orElse(GeneralTerminalEnum.PC_WEB);
                redisHelper.get(RedisDBIndexEnum.IDX36).del(jointLoginTokenKey(bo.getUserId(), terminal));
                result.set(true);
            }
        });
    }

    return result.get();
}

存在问题

  1. 目前Token在web端的存储方式为Cookie,某些浏览器开始禁用第三方的Cookie,导致我们的API客户出现无法登录的问题;
  2. 目前的认证方式只支持相同一级域名即chuangkit.com下的单点登录,不支持不同一级域名下的单点登录;
  3. 目前业务层与账号中心服务耦合严重,所有需要进行认证的接口都要RPC远程调用账号中心进行认证操作,代码重复开发,项目横向依赖。

目标

  1. 修改浏览器存储 Token 的方式为 LocalStorage,并且兼容历史 Cookie,解决三方Cookie被禁用的问题;
  2. 升级项目的认证令牌使用机制,支持不同一级域名下的单点登录;
  3. 搭建API网关,统一接口认证,认证通过后将用户信息携带给下游服务,消除服务间的横向依赖及代码重复的问题;

实现方案

如何实现不同域名下的单点登录,比较成熟的方案:自主实现、CAS、OAuth2等,其核心流程都是定义一个认证中心,认证中心负责用户的注册/登录以及自己域下的用户登录态维护,其它服务需要登录时跳转到认证中心,认证中心判断用户在自己域下是否有登录态,没有则先需要登录,有则携带token重定向回业务服务,业务服务拿到token后保存到自己的域下,然后请求业务接口。

方案对比:

自主实现CASOAuth2
复杂度简易一般复杂
Token存储方式兼容Cookie,支持LocalStorage只支持Cookie支持Cookie,LocalStorage
标准化一般较高,开源项目强,开放的标准协议
适用性适用,自主实现,从现有项目过渡相比其它来说较为便捷,比较适合小型项目不适用,基于cookie,支持localStorage的话需要二开,很多功能用不到基于OAuth2,概念多,使用场景全比较复杂,该方案实现的话改动较大,并且前后端需要对其有一定的了解,同时是一个标准协议,通用型较高
接入难度一般,单Token模式CAS Server只能单独部署官方提供的war包,适合从0到1。较高,双Token模式(accessToken和refreshToken)
推荐程度建议不建议人员/时间充足的情况下建议
实现方案:

完整流程:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=%2FUsers%2Fwangxt%2Fmyspace%2Fwxt%2F%E5%9B%BE%E7%89%87%2F%E8%AE%A4%E8%AF%81%E6%B5%81%E7%A8%8B%E5%8D%87%E7%BA%A7.png&pos_id=img-LMPNIsAI-1728789321451

前端SDK细节流程:

  1. 前边提到login.js作为一个拓展功能,哪个业务前端引入便跟随其部署在哪个项目里,这样login.js只能往当前前端项目所属域名下操作,无法实现多域名的交互,所以需要单独部署一个登录页面的项目,login.js负责和登录页面进行认证相关交互,业务前端系统仍然只需要实现相关回调方法即可,无需关注登录相关细节。
    在这里插入图片描述

原文地址:https://blog.csdn.net/weixin_40243894/article/details/142895674

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!