MaaAssistantArknights / MaaBackendCenter

MAA Copilot Backend
https://prts.plus
GNU Affero General Public License v3.0
73 stars 50 forks source link

feat: 兼容原登录系统的基础上,接入 Maa Account #138

Open Lixuhuilll opened 1 year ago

Lixuhuilll commented 1 year ago

111

使用了兼容原有登录系统的方法,目前流程如下:

用户点击登录按钮 -> 访问后端的 /oidc/authorization/maa-account 页面 -> 触发重定向到 Maa Account 登录页面 -> 登录成功携带 Token 返回作业站前端的 /oidc/callback/maa-account 页面 -> 作业站前端获取 URL 参数,并原封不动通过 GET 请求发送给后端的 /oidc/callback/maa-account 接口 -> 后端通过 Token 从 OIDC 服务器获取用户信息 -> 与作业站数据库用户进行邮箱比对,若用户不存在,则通过使用 OIDC 获取的用户信息创建一个用户 -> 后端调用现有的 JWT 认证登录模块,登录通过 OIDC 获取到的邮箱 -> 后端返回登录信息,返回的信息格式与 /user/login 接口完全一致,后续的使用方法也完全一致。

前端适配时需要记得允许 ajax 调用 /oidc/callback/maa-account 接口时的 GET 请求携带cookie、session,以 axios 为例的话就是让本次请求临时启用 withCredentials: true,因为 Spring Security 请求 OIDC 时默认会缓存一些信息到 Session 中,回调时从 Session 中取出数据进行比对。

Lixuhuilll commented 1 year ago

目前使用邮箱作为标识符,目前的Maa Account不能修改邮箱,因此工作正常。如果日后 Maa Account 新增修改邮箱功能,那么就需要使用 OpenID 作为唯一标识符,否则会出现账户丢失的异常情况。

Lixuhuilll commented 1 year ago

新的登录流程去除了对 Session 的依赖,主要修改:

① “访问后端的 /oidc/authorization/maa-account 页面 -> 触发重定向到 Maa Account 登录页面 ”

修改为: 使用 GET 请求后端 /oidc/authorization/maa-account 接口,接口响应:

{
    "status_code": 200,
    "data": {
        "serial": "string",
        "redirect_url": "string"
    }
}

前端需要临时存储流水号待后续使用,并跳转到 redirect_url。 流水号默认的有效期为 20 分钟,并且是一次性的。 redirect_url 的值是组装好的 Maa Account 登录页面的完整地址。

② “作业站前端获取 URL 参数,并原封不动通过 GET 请求发送给后端的 /oidc/callback/maa-account 接口”

修改为: 作业站获取 URL 参数, 并取得事先储存的流水号。将 URL 参数原封不动通过 GET 请求发送给后端的 /oidc/callback/maa-account 接口,并且 Http 请求头必须有自定义请求头 "OIDC-Serial",请求头的值为流水号。

Lixuhuilll commented 1 year ago

后端部署的时候可以让网关限制一下 /oidc/authorization 下所有路径的 qps,毕竟这个接口会往 Redis 里面写数据,写多了怕出问题。 假定有持续的 45 Qps ,大概会让Redis上有100 MB左右的空间占用。 实际可以更高一点,毕竟正常情况下用户向这个接口请求肯定是要登录的,登录成功后会自动移除掉信息,而上述给出的数据是假定所有的用户都是那种不正常的用户,会导致有这么多空间占用。

Handiwork commented 1 year ago

代码逻辑没有看出问题,业务逻辑个人认为有待进一步讨论

Lixuhuilll commented 1 year ago

代码逻辑没有看出问题,业务逻辑个人认为有待进一步讨论

目前的业务逻辑你认为存在哪些问题?有什么改进的方向吗?

dragove commented 1 year ago

@LiamSho 佬,可以给下流程上的建议吗?

Lixuhuilll commented 1 year ago

改了一下 RedisCache ,现在 oidc 过程中的中间信息会使用 Jackson 序列化储存在 Redis,可读性更好,并且体积比 Java 序列化器更小。