Nginx 使用SpringCloudOAuth2的SSL/代理问题

Nginx 使用SpringCloudOAuth2的SSL/代理问题,nginx,spring-security,spring-boot,spring-security-oauth2,spring-cloud,Nginx,Spring Security,Spring Boot,Spring Security Oauth2,Spring Cloud,我改编了以下OAauth2 Spring云示例: / 我所做的唯一更改是在Authserver端使用JPA检查数据库中的凭据。除了在nginx代理后部署它之外,其他一切都很好。在上面的示例应用程序中,使用了Spring Boot和嵌入式Tomcat。我还正确配置了代理标头: server.tomcat.protocol-header=X-Forwarded-Proto server.tomcat.remote-ip-header=X-Real-IP 代理HTTP正在工作: accessToke

我改编了以下OAauth2 Spring云示例:

/

我所做的唯一更改是在Authserver端使用JPA检查数据库中的凭据。除了在nginx代理后部署它之外,其他一切都很好。在上面的示例应用程序中,使用了Spring Boot和嵌入式Tomcat。我还正确配置了代理标头:

server.tomcat.protocol-header=X-Forwarded-Proto
server.tomcat.remote-ip-header=X-Real-IP
代理HTTP正在工作:

accessTokenUri: http://uaa.sample.com/oauth/token
userAuthorizationUri: http://uaa.sample.com/oauth/authorize
到目前为止还不错,但我需要使用SSL(显然):

如果我切换到SSL,在auth服务器从authorize重定向回来之后,我将从客户端应用程序获得401。我捕获了HTTP流量,一切似乎都正常:

  • 获取对客户端应用程序的请求
  • 客户端应用程序重定向到/登录
  • /登录重定向到
  • 身份验证服务器重定向到
  • 登录后,再次调用authorize,服务器最终重定向到
HTTP和HTTPS的HTTP通信量完全相同,只是HTTP为最后一个请求设置了一个适当的引用器(AFAIK,在OAuth身份验证期间不检查引用器,对吗?):

HTTP:

HTTPS:

GET /login?code=212eRK&state=9prwi2 HTTP/1.1
Host: test.sample.com
...
Cookie: JSESSIONID=401EB8D1D1F4297160D518EC253A0CB5; XSRF-TOKEN=95a00a0d-3362-4e9b-b7eb-45addf2d10b4
...

---
HTTP/1.1 401 Unauthorized
来自客户端应用程序的相应日志消息:

Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Could not obtain access token.
你知道为什么使用代理和SSL不起作用吗?我很高兴分享更多的代码和/或日志输出


谢谢

SSO应用程序尝试将身份验证代码交换为令牌时,它似乎失败了。 在此之前的所有步骤都是浏览器重定向,这是SSO服务器上试图调用身份验证服务器的代码。 身份验证服务器上的SSL证书使用什么?它们是否由Java信任存储中具有CA的受信任方签名? 如果不是,这可能就是它失败的原因,因为BadCredentialsException是底层HTTP请求失败的最终结果

另一个选项是,没有直接从SSO服务器到身份验证服务器地址的路由


我相信最终将由Apache Commons HttpClient代码来处理请求,因此您应该尝试增加这些类(org.Apache.http)的调试,看看它报告了什么。

也许值得仔细看看BadCredentialsException冒泡的原因,我的意思是使用调试器逐步完成Spring Security OAuth2代码

我之所以这样说,是因为根据我的经验,BadCredentialsException可能是由一个潜在的InvalidRequestException引起的,以下是违规的一行:

throw new InvalidRequestException(
                "Possible CSRF detected - state parameter was required but no state could be found"); 
我在这里就上述问题提出了一个单独的问题:


因此,就您的情况而言,对于新引入的nginx代理,我只是想知道您是否看到了一个误导性的异常。也就是说,在oauth2和使用CSRF的spring security oauth2方面,对未经培训的人来说是一种误导。这可能有点晚了,但我遇到了完全相同的事情

我的设置是一个使用Spring oAuth2对正在运行的Spring引导应用程序进行SSL代理的NGINX

要在nginx config中解决此问题

 proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;  
 proxy_set_header X-Forwarded-Proto  $scheme;  
在您的spring应用程序.yml

 server.tomcat.remote_ip_header: X-Forwarded-For
 server.tomcat.protocol_header: X-Forwarded-Proto
 security.require_ssl: true
资料来源:

现在,Spring检测到正确的URL,并请求。getRequestURL现在返回正确的URL,包括https://

 @Controller
 public class HomeController {
     @RequestMapping("/")
     @ResponseBody
     public String rootLandingPage(HttpServletRequest request) throws Exception {
         return "url: " + request.getRequestURL();
     }
 }

日志可能会告诉您(调试
org.springframework.security
)的日志。@DaveSyer我也有同样的问题。调整日志级别并没有透露更多关于可能的根本原因的信息。我无法从这一级别的详细信息中分辨更多。一个示例应用程序会有很大帮助。我只是花了一些时间通过我的调试器运行类似的情况。在我的例子中,在引发BadCredentialsException的点上,基础链接异常是InvalidRequestException,消息为:可能检测到CSRF:状态参数是必需的,但找不到。BadCredentialsException在某种程度上误导了我的天真(csrf问题)。我在尝试获取网络代理背后的oauth(uaa/oauth/token)令牌时收到了示例错误。执行此操作后,我在请求中获得了重定向URI,https://localhost/login/google,与为OAuth客户端授权的不匹配。参观https://console.developers.google.com/apis/credentials/oauthclient/477999739807-d0t4443rdep6jfnmjr4aufuh389tn2sk.apps.googleusercontent.com?project=477999739807 更新授权重定向URI。对于我来说,将JDK更新为最新版本解决了问题,因为根本原因是SSL握手。当我打开安全调试日志记录时,我开始看到此异常-由以下原因引起:sun.Security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径
 server.tomcat.remote_ip_header: X-Forwarded-For
 server.tomcat.protocol_header: X-Forwarded-Proto
 security.require_ssl: true
 @Controller
 public class HomeController {
     @RequestMapping("/")
     @ResponseBody
     public String rootLandingPage(HttpServletRequest request) throws Exception {
         return "url: " + request.getRequestURL();
     }
 }