Spring Cloud Zuul Proxy 背后的 Spring OAuth 授权服务器
Posted
技术标签:
【中文标题】Spring Cloud Zuul Proxy 背后的 Spring OAuth 授权服务器【英文标题】:Spring OAuth Authorization Server behind Spring Cloud Zuul Proxy 【发布时间】:2015-07-31 09:04:40 【问题描述】:我目前正在开发一个基于微服务架构的应用程序。我们使用使用 Spring Cloud Netfix 的 Zuul 服务器实现的 API-Gateway 将请求路由到我们的微服务。
为了实现我们所有服务的单点登录,我目前正在使用 Spring Cloud Security 设置 OAuth2 服务器。服务器基本上只是 Dave Syer 的 Repo 中实现的副本和过去:https://github.com/dsyer/spring-security-angular/tree/master/oauth2/authserver
主要区别是我想通过 Zuul 代理将请求路由到我的 OAuth 服务器。这样我就不必直接公开我的 OAuth 服务器,并且可以动态添加和删除登录服务器。
问题是我不了解如何正确配置此设置。当我尝试访问 OAuth 服务器上的受保护资源时,我被转发到登录页面。这当然是意料之中的。但我不知道如何设置转发时使用的主机名和端口。我想要发生的是服务器转发到 Zuul 服务器上的端点,该端点将被代理回 OAuth 服务器。 (Zuul API-Gateway 应该是客户端曾经与之通信的唯一服务器。其他所有内容都将被隐藏。)
因为它是从HttpServletRequest
中的LoginUrlAuthenticationEntryPoint
读取主机和端口。但是服务器看到的请求是Zuul代理发送的请求。所以我被转发到一个内部 IP 而不是代理上的端点。
我尝试将WebSecurityConfigurerAdapter.configure(HttpSecurity)
中的登录页面的 URL 设置为我的 Zuul 代理的绝对 URL。但这只是导致我的应用程序抱怨重定向太多。 (可能在那里造成了循环。)
最好的设置方法是什么?
我是否必须通过覆盖 bean 来实现某种自己的转发策略? 我是否缺少配置选项? 我的想法本身是错的吗? (在他对How to avoid redirect to another host with Zuul?Dave Syer 的回答中,他说你通常不会代理这个,但没有解释原因。)【问题讨论】:
那么你到底如何处理这个问题? 能否请您补充一下您是如何整理和实施的? 我暂时接受了排名最高的答案。 【参考方案1】:更新:POC 可以在这里找到https://github.com/kakawait/uaa-behind-zuul-sample
您是否尝试过以下设置(在zuul
服务器上):
zuul:
routes:
uaa-service:
path: /uaa/**
stripPrefix: false
security:
# Disable Spring Boot basic authentication
basic:
enabled: false
oauth2:
sso:
loginPath: /login
client:
accessTokenUri: https://<zuul hostname>/uaa/oauth/token
userAuthorizationUri: https://<zuul hostname>/uaa/oauth/authorize
...
基本上它适用于我的项目,我唯一要做的就是禁用/uaa/oauth/token
路由上的CSRF
保护。
身份验证服务器应该开启
server:
# Use different context-path to avoid session cookie overlapping
context-path: /uaa
使用Spring-Cloud.Brixton.M3
测试
感谢@thomas-letsch,您应该像以下(示例)一样调整您的安全性
public void configure(HttpSecurity http) throws Exception
http.logout().and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/index.html", "/home.html", "/", "/uaa/oauth/**").permitAll()
.anyRequest().authenticated().and()
.csrf().csrfTokenRepository(getCSRFTokenRepository()).ignoringAntMatchers("/uaa/oauth/token").and()
.addFilterAfter(createCSRFHeaderFilter(), CsrfFilter.class);
【讨论】:
这也适用于我。我不得不从安全性中排除 /uaa/oauth 路径。从我的 WebSecurityConfigurerAdapter 中查看这部分: public void configure(HttpSecurity http) throws Exception http.logout().and() .antMatcher("/**").authorizeRequests() .antMatchers("/index.html", "/home.html", "/", "/uaa/oauth/**").permitAll() .anyRequest().authenticated().and() .csrf().csrfTokenRepository(getCSRFTokenRepository()).ignoringAntMatchers ("/uaa/oauth/token").and() .addFilterAfter(createCSRFHeaderFilter(), CsrfFilter.class); 在我个人的情况下,我重写了OAuth2ClientContextFilter
以支持URI
(不仅是URL
),因此我可以使用accessTokenUri: /uaa/oauth/token
。对于userAuthorizationUri
,我使用localhost
,就像关注userAuthorizationUri: http://localhost/uaa/oauth/authorize
一样。因此配置是可移植的(我不需要知道 UAA 的位置)。我为 github.com/spring-projects/spring-security-oauth/issues/671 打开了一个问题
有趣的方法。如我所见,它旨在在 zuul 服务器本身中提供一个授权点。但是,你告诉zuul真正的OAuth Server在哪里?我的意思是,您在 zuul 配置中提供了<zuul hostname>
以使其能够对自己进行授权,但是它如何知道真正的授权端点?
我创建了一个带有扩展文档的 poc,应该可以回答您之前的问题 github.com/kakawait/uaa-behind-zuul-sample【参考方案2】:
据我了解您的问题,spring-cloud-security
(对于 EnableOauth2Sso
部分)和 spring-cloud
(对于 zuul),这是不可能使用 zuul 代理对授权服务器的调用。
主要原因是spring-cloud-security
独立保护网关(并且在考虑之前)Zuul 路由的逻辑。
这意味着(来自 Dave Syer 的 OAuth2 示例的示例配置)spring.oauth2.client.*
配置
spring:
oauth2:
client:
accessTokenUri: http://localhost:9999/uaa/oauth/token
userAuthorizationUri: http://localhost:9999/uaa/oauth/authorize
clientId: acme
clientSecret: acmesecret
被认为是在允许任何访问 Zuul 的路线zuul.routes.*
此外,此设置使 客户端代理 能够存储两个 Cookie:一个用于网关,一个用于授权服务器。
我希望这会有所帮助。
【讨论】:
以上是关于Spring Cloud Zuul Proxy 背后的 Spring OAuth 授权服务器的主要内容,如果未能解决你的问题,请参考以下文章
spring-cloud-Zuul学习--典型配置重新定义spring cloud实践
Spring Cloud 微服务二:API网关spring cloud zuul
最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)