【发布时间】:2015-01-05 13:51:39
【问题描述】:
我有两个:本地主机上的 STS 服务器和 Spring Web 应用程序。它奏效了。我已经测试了 OAuth2 授权代码授予流程 - 完全正常。
我将 STS 移动到其他机器,Web 应用程序在获取访问令牌时出现问题 - 完整跟踪(从 STS 重定向后停止/错误;刚开始从:https://sts-machine/authz/oauth2-resource/oauth/token 端点获取令牌;停止在访问网址:https://localwebapp:7443/swd/webLogin?code=306b88903d394f0b8145b2e8035fd306&state=PtTrt8):
SEVERE: Servlet.service() for servlet [swdServlet] in context with path [/swd] threw exception
error="access_denied", error_description="Error requesting access token."
at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:144)
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:198)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:90)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:57)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:146)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:279)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://sts-machine/authz/oauth2-resource/oauth/token":Connection reset; nested exception is java.net.SocketException: Connection reset
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:557)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:510)
at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:136)
... 47 more
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:78)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:52)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:541)
... 49 more
所以当 webapp 尝试从https://sts-machine/authz/oauth2-resource/oauth/token 的访问令牌交换“代码”时,连接会重置。
有趣的事实:手动发出请求效果很好! (手动交换访问令牌的代码)使用 Chrome 应用程序“Advanced Rest Client Application”和“Fiddler”请求编写器进行测试。
我使用wireshark 嗅探了两台机器。两者的结果相同 - 屏幕截图:http://i.imgur.com/2AYstN0.png(其中:10.1.0.121 是 localwebapp 机器,并且:10.1.0.80 是 sts-machine)
为什么会重置连接?
配置详情:
localwebapp:在 tc Pivotal Server(有点像 Tomcat)上运行,Win 8.1
sts-machine:是 IIS 上的 Thinktecture 授权服务器,Win Server 2012
更新 1
我发现:
openssl s_client -connect sts-machine:443 不起作用,但是:
openssl s_client -connect sts-machine:443 -servername sts-machine 确实有效!这表明 Java 客户端上的 SNI 存在问题。试图解决设置系统属性的问题:jsse.enableSNIExtension 到 true,但没有任何成功... 如何强制 JVM 使用 SNI?
【问题讨论】:
-
当我将地址更改为没有 SSL 的地址时(HTTP 不是 HTTPS):
http://sts-machine/authz/oauth2-resource/oauth/token一切正常。所以我认为 SSL/TLS 层存在问题。我试图通过设置 JAVA_OPTS=-Dhttps.protocols="TLSv1,TLSv1.1,TLSv1.2" -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2 来强制 Tomcat 至少使用 TLSv1 "并在 server.xml SSL 连接器中设置 sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"。但是 https 连接仍然出现错误 500...有什么想法吗? -
SNI 仅在 Java 7 中可用,您正在运行该版本吗?您应该启用 JSSE 调试输出。
-
刚刚检查过 jinfo:
java.runtime.version = 1.7.0_60-b19所以默认情况下应该启用 SNI。我使用-Djavax.net.debug=SSL,handshake,trustmanager选项运行服务器,结果为 extended trace 。我还使用了简单的控制台SSLPoke 与 jre7 和 jre8-same 问题。 -
我在代理 (nginx) 中强制执行 TLS 时遇到了同样的问题。当我启用 SSL 调试时,或多或少相同的堆栈跟踪。你还发现了什么吗?
-
不幸的是,这对我来说仍然是一个未解决的问题。我没有找到合适的解决方案。因为在 IIS 上我只有一个网站,所以我在服务器端禁用了 SNI 选项,因此 JVM(“客户端”)不使用它。