每日一博 - 微服务权限一二事

Posted 小小工匠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一博 - 微服务权限一二事相关的知识,希望对你有一定的参考价值。

文章目录


概念普及

关于权限, 先了解几个核心的概念

  • 认证
  • 授权
  • 鉴权

认证

举个例子: 输入用户名/密码,点击登录后,后台执行的业务逻辑就是认证 ---------->验证用户名/密码是否正确,能否登录系统 , 这就是认证


授权

举个例子: 不同的用户拥有不同的权限是通过系统授权来实现的,授权就是授予相关用户或角色资源操作的权限, 当然了也有很多第三方系统的授权.


鉴权

举个例子; 同样的系统,不同的人登录成功后,拥有的权限是不一样的,当用户进行操作时,后台会验证是否能够进行相应的操作,这就是鉴权,即校验用户是否有相应资源的操作权限


单体应用下的 认证、授权、鉴权

我们知道了: 权限问题的核心就是解决认证、鉴权和授权问题。

我们先看看在单体应用中是如何处理上述问题的 。

认证的处理方式

单体应用中,对于用户登录,会先校验用户的用户名/密码,通常都涉及到密码的加密处理,一般的判断是加密后相应的密码是否与数据库中存储的密码相等,如果相等的话,则登录成功。

用户登录成功的话,一般会返回用户登录成功相关凭证。

  • 如果是JWT的话,则会返回Token
  • 如果采用的是会话的话,则会通过Set-Cookie返回SessionId给客户端

授权的处理方式

在单体应用中,授权即修改用户相关角色信息,或者修改角色相关权限信息。一般在用户重新登录后,最新的权限信息生效。


鉴权的处理方式

单体应用一般会通过拦截器(Spring Security、Apache Shrio本质上都是拦截器),拦截用户请求.

这里同样会根据鉴权方案是JWT还是HTTP会话分别处理

  • 如果是JWT的话,则会通过解密来获得用户信息
  • 如果是采用的会话的方式,则会根据会话ID,从存储中(这里一般是Redis)来获得用户信息.

不论是哪种方案,最终都是根据用户信息来对相应的请求进行权限校验。

鉴权一般有两种方式,但都是基于角色的。

  • 一种是基于角色的隐式鉴权,即根据角色直接判断是否拥有相应资源的操作权限,比如角色是管理员,就可以删除用户,角色是普通用户,只能查看用户信息。
    这种一般在简单的系统中比较适用,常用的方式是通过注解,表明哪个接口可以给哪个角色访问。但这种方式在复杂的系统中就会变得难以维护。

  • 另一种是基于角色的精准鉴权,此种鉴权方案,一般会给角色分配明确的权限,相应的鉴权方式为根据用户角色查出具体的权限集合,然后进行进一步判断。此种方式在复杂系统中更加有效方便。


微服务架构下的 认证、授权、鉴权

在微服务中,权限处理的认证、授权功能实现,跟单体应用没什么区别。

在微服务架构下权限处理唯一与单体应用不同的便是鉴权方式.

区别点: 鉴权不再集中在单体应用中了,鉴权被分散在了各个微服务中。所以问题的关键就变成了从哪里获取用户相关信息,然后在哪里进行鉴权。


鉴权方案一

从用户服务获取用户信息,然后各个微服务分别鉴权.

  • 所有对微服务的访问在经过网关后都统一先访问用户服务获取用户相关信息,包括角色信息、角色权限信息
  • 然后分别在各个微服务中进行鉴权,判断用户是否有权限进行相应的操作

  • 优点: 实现简单,对比单体应用的实现来说,只是换了个地方获取用户信息,权限相关的判断还是保留在各个微服务中。

  • 缺点:用户服务需要保证高性能、高可靠以及可扩展,并且随着服务的增多,每个服务都需要与用户服务交互,服务间调用可能会显得略加繁琐,不够简单优雅,同时每个微服务中的权限判断逻辑也都重复冗余。

结论: 不是很推荐这种方式。


鉴权方案二

从用户服务获取用户信息,然后在网关进行鉴权

第二种方案为从用户服务获取用户信息,然后在网关进行鉴权, 这样一来整个架构看起来清晰了很多。

我们可以发现: 将请求往具体的微服务透传的时候,带上了用户信息,这个用户信息可以放在HTTP Header中。为什么透传的时候要带上用户信息呢?因为后端具体的微服务业务可能需要获取当前用户的信息,但这里并不是用来鉴权,只是业务逻辑中用到了而已。

  • 优点:架构简单,对于鉴权来讲服务间调用交互更加简洁,并且后端微服务不需要冗余鉴权业务逻辑

  • 缺点: 同样是用户服务需要保证高性能、高可靠以及可扩展,并且鉴权逻辑需要在网关实现。

微服务的理想状态是高内聚低耦合,每个服务专注于自己的事,各个服务间功能独立,独立演进,so针对微服务鉴权还有没有更好的方案呢?


鉴权方案三

鉴权要做的事是判断用户有没有相应资源的操作权限,所以从微服务的基于业务拆分的原则基础上,鉴权放在用户服务是不是更合适?

所以上述方案将鉴权放在了用户服务来实现,我们不再需要调用用户服务来获取用户信息然后进行鉴权了,直接将用户的请求转发到用户服务,在用户服务中统一处理鉴权。

此种方案下网关要做的事也将更加专注,只做请求的转发即可,后端各个微服务也只需专注于自己的业务即可。

总结: 比较推荐的方案,并且应该能满足微服务架构下大多数系统的权限处理需求。

当然缺点是对用户服务的高性能、高可靠以及可扩展提出了更高的要求。


其他方案

除了上述三种鉴权方式,微服务架构下可能还有其他鉴权方式,比如共享用户信息缓存的方式,这种方式下,各个微服务统一从缓存获取用户信息,然后分别在各自进行鉴权。

基于此种方式也很容易想到一个优化的变种,即从网关获取缓存的用户信息,然后在网关进行鉴权。

当然采用此类鉴权方式的团队可能也有他们的考虑,更多的可能是出于性能的考虑。

至于为什么不推荐诸如此类的方式呢,我觉得我们在做系统架构的时候需要有自己的原则,其实对于很多问题我们可以有许多种解决方法,哪种方案比哪种好可能并不好说,甚至团队在方案的选择上还会有所争执,但如果在架构设计上团队有自己的指导原则的话,可能能够帮助我们在方案的选择上达成共识。个人在架构设计上的原则包括但不限于可维护原则、可扩展原则、简单性原则等,所以与其说此类方案不好,倒不如说这并不符合我的设计原则。


小结

我们这里介绍了微服务架构下三种鉴权的实现

  • 第一种方式是从用户服务获取用户信息,然后在各个微服务中鉴权
  • 第二种方式是从用户服务获取用户信息,然后在网关统一鉴权
  • 第三种方式不再需要获取用户信息,直接通过网关转发请求,在用户服务进行统一鉴权,各个服务的职责划分更加明确,也是推荐的实现方式。

除此之外,还介绍了一些其他的鉴权实现方案,问题的解决方案并不唯一,有时候也很难说出哪种更好,我们要有自己的设计原则。


以上是关于每日一博 - 微服务权限一二事的主要内容,如果未能解决你的问题,请参考以下文章

Photozoom图像放大的技术一二事

每日一博 - Java序列化一二事儿

nginx 与 tomcat 集群 一二事 - 简单介绍

session一二事

结对编程一二事

RabbitMQ 一二事 - 订阅模式(微信公众号模式)的应用