当前位置: 首页 > 科技观察

微服务权限处理,为什么这么难?

时间:2023-03-16 02:11:33 科技观察

应用拆分成微服务后,一个不可避免的问题就是权限问题。拆分后的微服务如何处理权限,如何保证满足业务需求,如何保持架构简单易维护?今天这篇文章,我们就来深入探讨一下微服务架构下的权限处理问题,看看这个没有最佳实践的领域,如何设计得更优雅,更符合业务需求。1、先了解几个关于权限的名词。相关的名词可能有很多,这些名词很可能会让你感到困惑或混淆(为了避免混淆,我就不列出这些名词了)。但是这篇文章会用到几个与权限相关的核心词。理解这几个词对于理解这篇文章是必不可少的,所以至少有以下三个关于权限处理的名词需要你先了解。(一)认证。(2)认证。(三)授权。让我们先谈谈身份验证。我们都使用各种系统,在进入系统之前,您需要输入您的用户名/密码。点击登录后,后台做的事情就是对你的用户名/密码是否正确,是否可以登录进行鉴权和验证。这就是身份验证的作用。让我们谈谈身份验证。在同一个系统中,登录成功后,不同的人有不同的权限。当您操作时,后台会验证您是否可以进行相应的操作。这就是鉴权,验证用户是否拥有相应的资源。经营权。最后说一下授权。通过系统授权,不同的用户拥有不同的权限。授权是授予相关用户或角色操作资源的权限。当然,授权也可能包括对第三方系统的授权,本文暂不讨论此类场景。其实对于大多数应用系统来说,权限处理最重要的就是解决上面三个词所描述的问题,即系统权限处理需要做的就是鉴权、鉴权和授权。2、如何在单个应用中实现鉴权、鉴权、授权?上面我们说明了权限问题的核心是解决鉴权、鉴权和授权问题。如果想了解微服务架构中如何处理权限问题,不如让我们先看看在单体应用中如何处理上述问题?让我们分解一下。(1)在认证单体应用中,对于用户登录,首先会验证用户的登录信息(用户名/密码),其中可能会涉及到密码的加密。一般判断加密后对应的密码是否与数据库中保存的密码相等,若相等则登录成功。如果用户登录成功,一般会返回用户登录成功的相关凭证。如果是JWT,会返回Token,如果是session,会通过Set-Cookie返回SessionId给客户端。(2)认证单体应用一般通过拦截器拦截用户请求(SpringSecurity和ApacheShrio本质上就是拦截器)。这里也会根据认证方案是JWT还是HTTPsession分别进行处理。如果是JWT,则通过解密得到用户信息。如果使用session方式,会根据sessionID从存储(这里一般是Redis)获取用户信息。无论采用哪种方案,最终都会获取到用户信息。验证相应请求的权限。这里需要注意的是一般有两种认证方式,但是都是基于角色的。一种是基于角色的隐式认证,就是根据角色直接判断你是否有相应资源的操作权限。例如,如果您的角色是管理员,则可以删除用户,如果您的角色是普通用户,则只能查看用户信息。这通常更适用于简单的系统。常见的方式是使用注解来表示哪个接口可以被哪个角色访问。但是这种方法在复杂的系统中变得难以维护。另一种是基于角色的精确认证。这种认证方案一般会为角色分配明确的权限。对应的认证方式就是根据用户角色找出具体的权限集,然后再做进一步的判断。这种方法在复杂系统中更为有效和方便。(3)授权在单个应用中,授权是指修改用户相关的角色信息,或者修改角色相关的权限信息。一般情况下,最新的权限信息会在用户重新登录后生效。3、如何在微服务架构下实现以上功能?实际上,在微服务中,权限处理的认证授权功能的实现与单体应用并无二致。从微服务业务拆分的原则出发,我们会为用户相关的业务单独创建一个用户服务。作为一个单独的微服务,用户服务在实现认证和授权功能时与单体应用保持一致。是的,即相应的用户登录信息校验、用户角色修改、角色权限修改都可以在用户服务中独立实现。因此,微服务架构下的权限处理与单体应用唯一的区别就是认证方式。为什么认证方式不同?因为身份验证不再集中在单体应用程序中,所以身份验证分散在每个微服务中。所以现在问题的关键是从哪里获取用户相关的信息,从哪里进行认证。我们来看一下微服务架构下的几种认证方案:第一种方案是从用户服务中获取用户信息,然后分别对每个微服务进行认证。如下图所示:上图中一共有三个微服务,分别是存储服务、订单服务、用户服务。对每个微服务的访问都需要进行身份验证。对应的认证方式是所有的微服务访问经过网关后,首先访问用户服务获取用户相关信息,包括角色信息和角色权限信息,然后在每个微服务中进行认证,判断用户是否具有执行相应操作的权限。上述方法的优点是实现简单。相比于单个应用的实现,只需要改变获取用户信息的地方,权限相关的判断仍然保留在各个微服务中。相应的缺点也很明显。用户服务需要保证高性能、高可靠性和可扩展性。随着服务的增加,每个服务都需要与用户服务进行交互。服务之间的调用可能会显得有些繁琐,不够简洁优雅,同时各个微服务中的权限判断逻辑也是冗余的。综上所述,我个人不推荐这种方式。其实对于第一种方案,我们可以稍作修改得到略显优雅的方案,如下图,见方案二:方案二是从用户服务中获取用户信息,然后进行鉴权在入口处,这样整个结构是不是看起来干净多了?(好东西总是看起来简单)大家可能看到了,当请求透传到具体的微服务时,是包含用户信息的,而这个用户信息可以放在HTTPHeader中。为什么透传的时候需要带上用户信息?因为后端具体的微服务业务可能需要获取当前用户的信息,但是这个并不用于鉴权,只是在业务逻辑中使用。第二种方式的优点是架构简单,服务间的调用交互对于鉴权来说更加简洁,后端微服务不需要冗余的鉴权业务逻辑。缺点还在于用户服务需要保证高性能、高可靠、可扩展性,认证逻辑需要在网关上实现。微服务的理想状态是高内聚低耦合。每项服务都专注于自己的业务。每个服务都有独立的功能和独立的演进。那么微服务认证有没有更好的方案呢?请看方案三:鉴权需要做的是判断用户是否有相应资源的操作权限,那么基于微服务的业务拆分原则,鉴权放在用户服务?因此,上述方案将鉴权放在了用户服务中。我们不再需要调用用户服务获取用户信息再进行鉴权。而是将用户请求直接转发给用户服务,认证统一在用户服务中处理。在这种方案下,网关也会更加专注于做什么。它只需要转发请求,后端微服务只需要专注于自己的业务即可。这个方案在我看来是一个推荐的方案,应该可以满足微服务架构下大部分系统的权限处理需求。当然,缺点是对用户服务的高性能、高可靠性和可扩展性提出了更高的要求。除了以上三种认证方式,微服务架构下可能还有其他的认证方式,比如共享用户信息缓存的方式。在这种方式下,各个微服务统一从缓存中获取用户信息,然后自行进行认证。基于这种方式,很容易想到一个优化变体,即从网关获取缓存的用户信息,然后在网关进行认证。我个人不推荐这样的认证方式。当然,使用这种认证方式的团队也可能有自己的考虑,更多的可能是性能方面的考虑。至于为什么我不推荐这样的方法,我觉得我们在做系统架构的时候需要有自己的原则。事实上,我们可以有很多解决方案来解决很多问题。可能不容易说出哪个解决方案比哪个更好。团队在方案的选择上还是会存在争议,但如果团队在架构设计方面有自己的指导原则,或许可以帮助我们在方案的选择上达成共识。我在架构设计上的原则包括但不限于可维护性、可扩展性、简单性原则,所以与其说这种方案不好,不如说不符合我的设计原则.写完最终的应用拆分微服务,一个不可避免的问题就是权限问题。权限问题中要解决的核心问题是认证、认证和授权。在讲解微服务架构下如何处理权限问题之前,我们先来看下单体应用下如何处理权限问题的鉴权、鉴权、授权。对于微服务来说,在权限问题的处理上与单体应用最大的区别就是认证的方式。身份验证和授权的实现与单体应用程序的实现没有太大区别。在微服务中的用户服务下就可以了。为什么微服务下的认证流程不一样?因为身份验证不再集中在单体应用程序中,所以身份验证分散在每个微服务中。所以问题的关键是在微服务下从哪里获取用户相关信息,在哪里进行鉴权。我们详细介绍了微服务架构下三种认证方式的实现。第一种方式是从用户服务中获取用户信息,然后在各个微服务中进行认证。第二种方式是从用户服务获取用户信息,然后在网关进行统一认证。第三种方式不再需要获取用户信息,直接通过网关转发请求,对用户服务进行统一认证。各个服务的职责划分比较明确,也是个人比较推荐的实现方式。此外,还介绍了一些其他的认证实现方案。解决问题的方法并不是唯一的,有时很难说出哪个更好。我们必须有自己的设计原则。谈论技术,而不仅仅是技术。