我改编了以下的OAuth2 Spring Cloud示例:
Authserver / SSO
我所做的唯一更改是在Authserver端使用JPA来检查数据库中的凭据。 一切运作良好,除了在nginx代理之后部署。 正如上面的示例应用程序中所使用的,使用Spring Boot和embedded式Tomcat。 我也正确configuration了代理标题:
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(显然):
accessTokenUri: https://uaa.sample.com/oauth/token userAuthorizationUri: https://uaa.sample.com/oauth/authorize
如果我切换到SSL,auth服务器从授权redirect后,我从我的客户端应用程序得到一个401。 我捕获的HTTPstream量,似乎一切工作:
HTTP和HTTPS的HTTPstream量是完全一样的,除了HTTP为最后一个请求设置了正确的引用者(AFAIK,在OAuth身份validation期间没有检查到引用者,对吧?):
HTTP:
GET /login?code=212eRK&state=9prwi2 HTTP/1.1 Host: test.sample.com ... Referer: http://uaa.sample.com/login Cookie: JSESSIONID=401EB8D1D1F4297160D518EC253A0CB5; XSRF-TOKEN=95a00a0d-3362-4e9b-b7eb-45addf2d10b4 ... --- HTTP/1.1 302 Found
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服务器上的代码,用于调用auth服务器。 您在auth服务器上使用什么SSL证书? 他们是否在Java信任存储中由具有CA的可信方签名? 如果没有,那么这可能是因为BadCredentialsException是底层HTTP请求失败的最终结果而失败的原因。
另一种选择是没有直接从SSO服务器到Auth服务器地址的路由。
我相信最终是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");
我在这里提出了一个单独的问题:
为什么AccessTokenRequest的PreservedState永远为空,并产生与CSRF相关的InvalidRequestException异常?
所以,根据你的情况,用新近推出的nginx代理,我只是想知道你是否可能没有看到一个误导性的例外。 也就是说,误导未被训练的oauth2和spring security oauth 2与CSRF是一个额外的复杂性来处理。
可能有点晚了,但我遇到了同样的事情。
我的安装程序是一个NGINX,通过使用Spring oAuth2执行一个运行的Spring Boot应用程序来进行SSL代理 。
在nginx配置中解决这个问题
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
而这在你的spring application.yml中
server.tomcat.remote_ip_header: X-Forwarded-For server.tomcat.protocol_header: X-Forwarded-Proto security.require_ssl: true
来源: http : //docs.spring.io/spring-boot/docs/current/reference/html/howto-security.html#howto-enable-https
现在,Spring检测到正确的URL,并且request.getRequestURL返回正确的URL,包括https://
@Controller public class HomeController { @RequestMapping("/") @ResponseBody public String rootLandingPage(HttpServletRequest request) throws Exception { return "url: " + request.getRequestURL(); } }