Auth鉴权中心总结

1. 需求

  1. 增加产品概念

    之前写的auth包括用户、组织、角色、权限等关系,在新的业务中,又提出了产品、项目等概念,要求:

    • 不同的产品使用同一套用户系统,一个账户可以在多个产品中使用
    • 目前的产品线中都有组织概念
    • 不同产品的角色权限系统是不同的,但有相似的用户、组织、权限管理的功能
  2. 业务使用方式

    方式1

    • 业务人员在后台给用户创建了组织,并设置开通的产品,用户可以对相应的产品进行访问

    方式2

    • 用户自己在一个产品上创建了组织,邀请了成员,设置了角色
    • 又想使用另外一个产品,系统返回尚未开通本产品,是否开通
    • 用户选择“是”,这时候组织又开通了另外一个产品线

    不论哪种方式都应该具备:

    • 不同的产品之间共享用户、组织、角色(部分)等内容
    • 角色分成公共的与产品特有的,公共角色指的是组织管理相关的橘色,在不同产品间互通,特有的角色是与产品的功能相关,产品间不互通。
    • 用户在不同产品之间访问可以应该是单点登录的,即:一个产品登录,其他产品都登录
    • 用户在不同产品产生的数据是独立的,不会出现在1个产品产生的数据,在另外一个产品中还能看到,即使是相同的功能。
  3. 服务维护方式

    有新的产品上线

    • 将服务启动起来,包括数据库、服务等
    • 向auth中心注册新产品,包括新产品的信息(code、url)、产品的权限、产品独有的角色、角色(包括公共与独有)与权限的关系等内容
    • 配置网关,将域名指向相应的服务
    • 进行相应的开通工作
    • 用户访问新产品
  4. 其他

    • PMS与PMP带来的启示

      • 组织切换互通:这种互通问题依然会存在,组织在产品之前,切换了组织也就切换了产品关系,能否访问该产品都受控于组织
      • 产品线数据互通:这个可以做到,首先是产品线中的功能尽量不交叉,如果交叉,部署新的服务,独立数据库,做到数据隔离。
    • 个人空间

      1. 个人空间给独特的组织标识

      2. 个人空间受控于产品,某些产品没有个人空间

      3. 获取用户所在组织时,根据不同产品,确定是否返回个人空间

    • 项目

      1. 有的产品有项目,有的没有项目。项目属于产品内部功能,不做产品间的同步;
      2. 项目中有人员,属于产品内功能;项目中的角色由组织控制,属于公共功能,项目中人员登录该系统时,看到的菜单与组织的看到的不同;
      3. 项目有生命周期;
      4. 项目中的功能一般与公司中的功能相对应,项目侧汇报,公司侧统计。
      5. 项目中功能的鉴权应该是:人员、项目、角色
      6. 项目可以进行切换
    • 后台管理系统

      1. 把后台看成一个产品
      2. 后台中负责各种管理工作
      3. 这个产品仅对多邦组织赋予

2. 分析

这里要做的,其实是一个用于多系统的鉴权中心,用于B端用户的单点登录及授权。

这里有两种方案可以来做,第一种以用户为中心,用户与产品做关联:

  1. 把用户系统独立出来,维护用户信息,做登录、退出等工作,单独的服务;
  2. 组织、权限、产品线抽象到一起,一个代码,多个产品起多个服务,不同的数据;
  3. 多个系统先通过nginx,然后再通过各自的gateway,在gateway中进行认证与鉴权

第二种以组织为中心,组织与产品做关联:

  1. 用户、组织、角色、权限、产品都在一起成为独立与产品的权限中心
  2. 组织与产品关联,给组织开哪些产品先

以目前看,我们的潜在用户有2类:小公司有多个项目情况,大的项目情况,不论哪种情况都是以组织为中心的,所以使用第2种方案更好一些。

这样就来看看常用的单点登录

单点登录的方式是多系统共享用户资源的OAuth方式,除此之外各个系统之间相互独立。

对应于B端,不仅仅是用户资源,组织、角色、权限等都是共享的资源,需要考虑的就会更多一些。

目前各个系统都是同一顶级域名下的不同子域名形式。

基于以上条件,统一的auth-server来对各个产品鉴权,它们使用同一token,虽然是不同的产品线,但对于后端而言,它们更像是一个系统,类似于将之前PMS中不同模块用多个前端封装成不同产品。

  • 鉴权如何做辨析

    1. 第一种:与单系统的类似,网关向鉴权中心去请求,鉴权中心做好缓存;

      这种有一种jwt的方式,将权限直接封装到token中,但这样对权限的修改不方便,会造成重新登录或者额外的逻辑去补偿,不太合适;

    2. 第二种:各服务自己进行鉴权;

      权限统一有auth来管理,各个产品并不发自己的token,若是产品各自发token,那么各产品要自己做一次鉴权

  • token的刷新问题

    通过refresh_token来对token进行更新

3. 设计

3.1 结构

目前的网关是做限流、鉴权等工作的,而不同的产品其鉴权的策略不同,如有项目的产品与没有项目的产品就存在差异:

nginx做最前端的网关,各个产品使用自己的网关,鉴权在各个产品线自己的网关中完成;

最外层的nginx也可以不要,各个产品使用自己网关即可,因为他们往往并不是部署在一台机器上;

整个系统使用一个域名,不同产品使用一个子域名,不同产品中的各个服务通过路由来做区分;

总体的结构示意图:

Auth总体结构图

在这里将用户、组织、产品、角色、权限抽象成一个auth;

将项目、项目与组织关系、项目与用户关系、项目中角色抽象成独立的prioject-auth,这块逻辑既可以包含在各个server内部,也可以是单独的server,看以后服用的情况。这里按单独server来构思。

auth关系图:

Auth内部关系图

project-auth关系图:

private-auth-server关系图

流程一般为:由各自的客户端出发,进入网关,然后进入业务server,在业务server中,向project-auth进行鉴权

3.2 流程

这样,与单系统的鉴权相比,除了初次的一些重定向略有不同,其余的基本相同。

4. 鉴权

认证过程已经在Gateway文章中做了介绍,这里不在赘言了,对于鉴权,这里再说一下。

  • interceptor

    这里将鉴权interceptor封装到了common包中,这样common包需要依赖Auth进行用户权限的查询,这里使用Feigin。

  • app.authorization配置项

    考虑到有的情况下可能没有鉴权,所在在追加addInterceptor之前,进行该配置项的判断,只有为true时,才可以使用

    使用@ConditionalOnProperty,参考

  • 增加AuthorizationConfig

    考虑到一来每次在业务服务中addInterceptor麻烦,二来project的Authorization并不是相同的逻辑,这里增加了AuthorizationAutoConfig来自动进行addInterceptor,并且只有ConditionalOnSingleCandidate时,才自动注入。这样以后如果有project,在各自的project实现一个AuthorizationConfig就好。

    出现了循环依赖的问题,增加@Lazy解决,参考

    出现ConditionalOnMissBean不好使,发现其自身也在其中,使用@ConditionalOnSingleCandidate解决,参考

  • 这样使用鉴权的流程为

    1. 依赖 common
    2. 配置 app.authorization=true
    3. application启用Feigin:EnableFeignClients(basePackages = {})

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×