在 REST 微服务上使用 Zuul Proxy、Oauth2 实现身份验证和授权

Posted

技术标签:

【中文标题】在 REST 微服务上使用 Zuul Proxy、Oauth2 实现身份验证和授权【英文标题】:Implementing authentication and authorization using Zuul Proxy, Oauth2 on REST Microservices 【发布时间】:2019-06-17 08:06:51 【问题描述】:

我正在尝试使用 Spring Boot 在工作流中实现上述架构。

Web 客户端通过 Zuul 代理向资源服务器(微服务端点)发出请求。 Zuul Proxy 重定向到 oauth2 服务器进行身份验证。 无论请求是否经过身份验证,Oauth2 都会重定向到 Zuul 代理。 如果未通过身份验证,Zuul 会使用未经身份验证的响应重定向 Web 客户端。 如果经过身份验证,Zull 代理将重定向到请求的微服务端点。 微服务端点检查用户是否被授权(用户级访问)访问资源。 微服务还可以对其他微服务进行内部休息调用。 最后,请求的资源被发送回客户端。

我想确保我遵循正确的工作流程。

我想知道是否有任何解决方案实现了类似的保护微服务 API 的解决方案。

我对以下内容感到困惑:

我们如何将用户详细信息传递给微服务,以便微服务可以执行自己的用户授权级别? 是否应该将 OAuth2 访问令牌标头传递给每个微服务,以便微服务可以单独验证令牌? 每个微服务是否应该使用秘密凭证来验证访问令牌,以使令牌不能沿着请求链伪造?

我知道这是一个有点冗长的问题。但我还没有找到上述架构的合适解决方案。

【问题讨论】:

请在此处分享您的发现。我认为这是让微服务协同工作的一种非常好的方式,并且我希望这样做 请在此处查看 Zuul 作为 OAuth2.0 客户端:baeldung.com/spring-security-zuul-oauth-jwt @Ananda:如果你成功了,你介意在这里放一些细节吗? 【参考方案1】:

很遗憾,我没有完整的答案,只有部分:

一旦 zuul 代理可以使用 JWT 令牌,那么每个微服务都可以通过配置其资源服务器来授权请求​​,例如

 @Override
  public void configure(HttpSecurity http) throws Exception 
    http
        .authorizeRequests().anyRequest().access("#oauth2.hasScope('microserviceA.read')").and()
        .csrf().disable()
        .httpBasic().disable();
  

范围可以由带有数据库的 oauth 微服务管理 - 根据客户端凭据,它将获取范围信息并编码为 JWT 令牌。

我目前不知道 - 如何让 zuul 代理使用“Web 客户端”凭据来通过 oauth 授权自己 - 我不想硬编码 zuul 代理凭据,因为那时 web-不会使用客户信用。

我刚刚发布了关于这个主题的类似问题: Authorizing requests through spring gateway with zool via oauth server

更新: 我发现描述几乎这种配置的文章(没有 eureka,但从我的经验来看并没有增加太多复杂性):https://www.baeldung.com/spring-security-zuul-oauth-jwt,有 github 项目和源代码。不幸的是,源代码没有被完善,因为它被作者用于他的商业课程。 但是我已经设法从他的示例工作集中进行构建。

总结:在所描述的架构中,每个资源服务器(微服务 A、B、..)从请求客户端接收由 zuul 代理/网关转发的 JWT 令牌。令牌在请求标头中转发。如果没有提供有效令牌,则网关会将请求重定向到授权页面。 此外,每个资源服务器都可以使用 oauth 服务检查令牌,如果需要,请按照我上面写的进行范围检查。

【讨论】:

【参考方案2】:

我一直在努力解决基于 Spring Cloud 解决方案的微服务架构的相同安全设计问题。我只发现这篇文章对此有所了解:https://developer.okta.com/blog/2018/02/13/secure-spring-microservices-with-oauth

但它与 Okta sso 服务提供商有关,而不是其他 oauth2 服务器(如 keycloak)的通用解决方案。

我还看到了一些关于如何使用 oauth2 服务器保护网关和微服务的解决方案,如下所示: https://github.com/jgrandja/oauth2login-gateway

但它没有考虑到网络客户端。

【讨论】:

第二个链接是基于Spring Cloud Gateway而不是Zuul的实现。【参考方案3】:

我不确定你是否能够解决这个问题,我可以看到这还没有回答,但是有一种方法可以将所有信息从 JWT 传递到所有下游微服务。 编写自己的 ZuulAuthenticationFilter,然后创建下面的方法

private void addClaimHeaders(RequestContext context, String token) 
    
    try 
        
        Map<String, Claim> claims = jwtTokenVerifier.getAllClaims(token);
        claims.forEach((key, claim) -> 
            
            context.addZuulRequestHeader("x-user-info-"+key, String.valueOf(claim.as(Object.class)));
        );
        
    catch(Exception ex) 
        
        log.error("Error in setting zuul header : "+ex.getMessage(), ex);
    

这样,您将在每个微服务的标头中从 JWT 获取信息,以“x-user-info-”开头的标头将包含您的 JWT 详细信息

【讨论】:

【参考方案4】:

在以下链接中有上述架构的实现: https://www.baeldung.com/spring-security-zuul-oauth-jwt

【讨论】:

以上是关于在 REST 微服务上使用 Zuul Proxy、Oauth2 实现身份验证和授权的主要内容,如果未能解决你的问题,请参考以下文章

11 微服务集群网关Zuul介绍

spring cloud 入门系列六:使用Zuul 实现API网关服务

Zuul 不转发请求到其他微服务

Zuul网关

微服务架构 | 6.1 使用 Zuul 进行服务路由 #yyds干货盘点#

Spring Boot 如何在 Zuul 微服务上验证令牌