我已经使用spring的sparklr示例应用程序和我在网上找到的几个示例实现了spring oauth2的资源所有者流程。我使用curl测试了令牌请求部分,以便提供客户端和用户凭据:
curl -v --data "username=user1&password=user1&client_id=client1&client_secret=client1&grant_type=password" -X POST "http://localhost:8080/samplerestspringoauth2/oauth/token"
并且它正常工作,但是我做了以下观察:
虽然根据我看到的示例,我使用了BasicAuthentication过滤器,但这并没有真正用于安全过程。由于令牌请求不包含Authentication头,因此BasicAuthentication过滤器只会跳过任何检查。 ClientCredentialsTokenEndpointFilter和authentication-server是唯一在令牌请求期间执行安全检查的人。在注意到并通过调试验证后,我试图完全删除以下部分:
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
来自配置。但后来我收到了警告:
“无法建立AuthenticationEntryPoint。请确认 您有通过命名空间配置的登录机制(例如 form-login)或使用。指定自定义AuthenticationEntryPoint 'entry-point-ref'属性“。
下一步,我在http命名空间中添加了entry-point-ref =“clientAuthenticationEntryPoint,并删除了警告。我测试了应用程序并正确播放。
但是,除了上述内容外,我还在调试过程中进行了以下观察: ClientCredentialsTokenEndpointFilter在私有变量中包含自己的OAuth2AuthenticationEntryPoint入口点,并在由于错误的客户端凭据失败时使用它。 因此,无论在基本过滤器中还是在http命名空间中指定的入口点都无关紧要。最后,ClientCredentialsTokenEndpointFilter将使用自己的私有OAuth2AuthenticationEntryPoint。 总结我的结论似乎如下:
下面我将令牌请求的http和端点配置作为参考。我跳过其余的配置以保持帖子易于阅读:
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
我还假设在令牌请求的原始sparklr应用程序(即spring oauth2示例应用程序)配置中也发生了同样的问题,这非常相似。这可以在https://github.com/spring-projects/spring-security-oauth/blob/master/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml找到,相关部分如下:
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/**" method="GET" access="ROLE_DENY" />
<intercept-url pattern="/**" method="PUT" access="ROLE_DENY" />
<intercept-url pattern="/**" method="DELETE" access="ROLE_DENY" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
我希望spring oauth2能够更恰当地与spring spring进行交互,而不必使用不必要的误导性配置,这让我觉得我可能错过了一些东西。由于安全性是一个敏感方面,我想与您分享,并询问我的结论是否正确。
答案 0 :(得分:11)
/ oauth / token提供了两种不同的方法来验证请求令牌的客户端:
使用HTTP-Basic身份验证(当&#34; http-basic&#34;元素存在时)
使用org.springframework.security.web.authentication.www.BasicAuthenticationFilter处理身份验证并处理&#34;授权&#34; HTTP标头,包含客户端的base64编码凭据。过滤器仅在存在Authorization标头时执行处理。始终首先尝试此方法。只有当用户提供了&#34;授权&#34;时,才会调用http-basic上定义的入口点。包含无效内容的标头 - 这就是为什么您没有看到调试器中调用的入口点,尝试设置授权HTTP标头并且您的断点会受到影响。
使用client_id和client_secret HTTP参数在OAuth标准中定义
这是使用org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter处理的,默认情况下使用入口点将WWW-Authenticate标头发送回客户端。可以自定义默认入口点(这是一个setAuthenticationEntryPoint方法)。只有在提供client_id参数时才会使用入口点。
这两种方法都使用不同的方法来获取客户端的用户名+密码,但是对同一个身份验证管理器进行验证。
可以建立&#34; No AuthenticationEntryPoint&#34;取出&lt; http-basic&gt;时出现的错误element来自Spring Security本身,而不是来自OAuth扩展。原因是Spring Security无法判断自定义过滤器ClientCredentialsTokenEndpointFilter中是否已经配置了默认入口点。并且Spring Security的HTTP配置总是必须至少有一个入口点。
因此,完整的逻辑如下:
关于你的观察:
&GT;&GT;如果我们指定了基本过滤器,则不使用基本过滤器,可以将其删除 而不是http命名空间中的端点。
&GT;如果您使用client_id + client_secret
对客户端进行身份验证,则情况确实如此&GT;&GT;在http命名空间中指定基本过滤器或端点是 只需要编译器停止警告。他们没有 实际使用,使用的端点是硬编码的 ClientCredentialsTokenEndpointFilter。
&GT;部分正确,因为在缺少client_id的情况下将使用入口点。
配置确实令人困惑(部分原因是OAuth不是Spring Security的本机部分,而是扩展),但所有这些设置都有意义并且在特定情况下使用。
您所做的更改不会产生任何安全隐患。