聊天的时候被问到,“单设备/多设备/单点登录的架构如何设计?”

1.单设备登录

先来讲讲单设备登录的问题,会有人把单点登录和单设备登录混为一谈的,注意这两者完全不一样

单设备登录到底应该怎么实现呢?

通过Username作为key,确保一个用户只能够对应一个Token,以此来实现用户的单设备登录

注意一个点,我们是可以在Token里面保存一些数据的,比如username

举个例子;

你在PC端登录成功了,此时后端在Redis里面存储了 username:token1 的键值对,在你的浏览器本地保存了Token

此时你在手机端进行登录,此时后端又会将你此次登录生成的Token放入到Redis里面

即将原来的username:token1改为了username:token2,然后你再回到PC端进行操作

当PC端进行操作时,带上了在PC端登录的时候保存的Token1去Redis里面进行验证

此时该username对应的Token已经是Token2了,不是Token1了,就会验证失败要求你重新登录

2.多设备登录

多设备登录,即你即可以在电脑端登录该网站,也可以在手机端或者ipad端登陆该网站,实现"多地"登陆

在这里我们可以这样设计,对每个端我都生成不一样的Token,这些Token都对应着用户信息

在每个端访问的时候,带上各自独立的Token,以此实现多设备登录

大家觉得这样的设计方案合理吗?有什么问题吗?

如果Redis存储的时候是这样设计话,那是不是意味着我可以多台电脑同时登录同一个网站的同一个账号了?

那是不是我有多台手机我也能在多台手机中同时登录同一个网站的同一个账号,这样合理不?

3.多设备登录 --- 同种设备不允许多地登陆

针对上面的第二种实现方式的问题,我们考虑到同种设备多次登录的情况,我们希望的是同种设备只能有一部进行登录

这里是对方案二的改进,我们将username作为Key,但是不是只有一个username,那样的话是能对应一个Token了,就是单设备登录了

那我就设计成三个username作为Key,pc_username、mobile_username、ipad_username

每个username分别对应不同端的设备,目前就是电脑、手机和Ipad了。

那我们如何得知用户到底是哪种设备呢?

我们可以基于HTTP请求头部中的User-Agent字段,该字段包含了浏览器或客户端发送的关于自身信息的数据,包括设备类型等...信息

  1. 后端解析User-Agent:

    当用户发起登录请求时,服务器读取请求头中的User-Agent字符串

  2. 识别设备类型:

    通过验证User-Agent的内容来识别设备类型,如"Mobile"、"iPhone"、"iPad"、"Android"、"Windows NT"等

  3. 对不同设备进行分类:

    根据解析结果将设备大致分为手机、平板和电脑,如果User-Agent中包含"iPhone"、"Android"或其他智能手机标识,则认为是手机;如果包含"iPad"或者特定的平板标识符,则认为是平板;若包含"Windows NT"、"Macintosh"或常见桌面浏览器标识,则可能判断为电脑。

  4. 进行登录控制策略

java 复制代码
public void getRequestHeader(HttpServletRequest request){
    // 从浏览器获取请求头信息
    String info= request.getHeader("user-agent");
    if(info.contains("Windows")){
        System.out.println("Windows pc端登陆");
        return;
    }
 
    if(info.contains("Macintosh")){
        System.out.println("Mac pc端登陆");
        return;
    }
 
    if(info.contains("Android")) {
        System.out.println("Android移动客户端");
        return;
    }
 
    if(info.contains("iPhone")) {
        System.out.println("iPhone移动客户端");
        return;
    }
 
    if(info.contains("iPad")) {
        System.out.println("iPad客户端");
        return;
    } 
    System.out.println("其他客户端");
}

4.单点登录

有人可能会把单点登录和单设备登登录混为一谈,具体的区别大家可以看我的这篇文章:Session?单点登录?JWT? 一篇看懂 - 掘金 (juejin.cn)

这里拓展一下单点登录的架构设计

在单体架构的服务中,以Java举例,单个SpringBoot服务中,是不需要考虑单点登录的问题的,反正就一个整体服务对外提供服务

根本不会存在单点登录的问题,那么微服务的单点登录真的是你想的那样吗?

  • 每个应用单独对token进行去验证

这么一看这样好像没什么问题,挺好的,但是不觉得功能有点耦合了吗,每个应用都需要单独的去验证token是否有效,用户是否登录

我们能不能把登录认证、权限认证单独抽出来进行统一鉴权

  • 网关统一鉴权

auth服务:这个服务承载了我们所有的基础数据源。他不管鉴权,只管数据相关的持久化操作以及业务操作,提供出各种各样的权限相关的接口。

gateway网关层:对所有请求进行鉴权,避免每个服务对鉴权进行耦合

相关推荐
星星在线1 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒2 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x2 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
保持当下3 小时前
分享一些程序员很棘手但是却又简单的工具
程序员·免费·js·工具
袋鱼不重3 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
用户8356290780513 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还3 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
Hommy884 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api
CaffeinePro4 小时前
FastAPI响应处理:返回值、状态码、响应头与异常标准化与案例解析
后端