Spring oauth2令牌请求中未实际使用的基本身份验证过滤器和身份验证入口点 [英] Basic Authentication Filter and authentication entry point not actually used from spring oauth2 token request

查看:128
本文介绍了Spring oauth2令牌请求中未实际使用的基本身份验证过滤器和身份验证入口点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经基于spring的sparklr示例应用程序和我在网上找到的几个示例,使用spring oauth2实现了资源所有者流程.为了提供客户端和用户凭据,我使用了如下所示的curl测试了令牌请求部分:

I have implemented resource owner flow with spring oauth2 based on spring's sparklr sample application and a couple of samples I found online. I tested the token request part with curl like this in order to provide both client and user credentials:

curl -v --data "username=user1&password=user1&client_id=client1&client_secret=client1&grant_type=password" -X POST "http://localhost:8080/samplerestspringoauth2/oauth/token"

它可以正常工作,但是我观察到以下情况:

and it works correctly, however I have made the following observation:

尽管根据我看到的示例,我使用了BasicAuthentication过滤器,但是在安全过程中并没有真正使用它.由于令牌请求不包含Authentication标头,因此BasicAuthentication过滤器将跳过任何检查. ClientCredentialsTokenEndpointFilter和authentication-server是唯一在令牌请求期间执行安全检查的程序.在注意到这一点并通过调试对其进行验证后,我尝试完全删除以下部分:

Although according to the examples I saw, I make use of the BasicAuthentication filter, this is not really used in the security process. Since the token request does not contain an Authentication header, the BasicAuthentication filter just skips doing any checks. ClientCredentialsTokenEndpointFilter and authentication-server are the only ones performing security checks during the token request. After noticing this and verifying it via debugging, I tried to remove completely the following part:

<http-basic entry-point-ref="clientAuthenticationEntryPoint" />

来自配置.但是后来我得到了警告:

from the configuration. But then I got the warning:

无法建立AuthenticationEntryPoint.请确保 您具有通过名称空间配置的登录机制(例如 表单登录)或使用以下命令指定自定义AuthenticationEntryPoint 'entry-point-ref'属性".

"No AuthenticationEntryPoint could be established. Please make sure you have a login mechanism configured through the namespace (such as form-login) or specify a custom AuthenticationEntryPoint with the 'entry-point-ref' attribute".

下一步,我在http名称空间中添加了entry-point-ref ="clientAuthenticationEntryPoint,并且摆脱了警告.我测试了该应用程序并正确播放.

As a next step, I added the entry-point-ref="clientAuthenticationEntryPoint in the http namespace, and got rid of the warning. I tested the app and played correctly.

但是,除上述内容外,我还在调试过程中进行了以下观察: ClientCredentialsTokenEndpointFilter在私有变量内包含其自己的OAuth2AuthenticationEntryPoint入口点,并在由于错误的客户端凭据而失败时使用该入口点. 因此,在基本过滤器或http名称空间中指定哪个入口点都没有关系.最后,ClientCredentialsTokenEndpointFilter将使用其自己的私有OAuth2AuthenticationEntryPoint. 总结我的结论似乎如下:

However, in addition to the above, I have also made the following observation during debugging: The ClientCredentialsTokenEndpointFilter, contains its own OAuth2AuthenticationEntryPoint entry point inside a private variable, and uses that when failing due to wrong client credentials. Therefore, it does not matter what entry point I specify either in the basic filter, or in the http namespace. At the end ClientCredentialsTokenEndpointFilter will use its own private OAuth2AuthenticationEntryPoint. To summarize my conclusions seem to be the following:

  • 如果我们指定了以下基本过滤器,则可以将其删除 HTTP命名空间中的终结点.
  • 指定基本 过滤器,或者仅在http名称空间中需要端点 编译器停止警告.它们没有实际用途,并且 使用的端点在内部进行了硬编码 ClientCredentialsTokenEndpointFilter.
  • The basic filter is not used and can be removed, if we specify the endpoint in the http namespace instead.
  • Specifying either a basic filter,or an endpoint in http namespace is needed only for the compiler to stop the warning. They have no practical use, and the endpoint used is hardcoded inside ClientCredentialsTokenEndpointFilter.

下面,我将令牌请求的http和终结点配置放在上面,以供您参考.为了使文章易于阅读,我跳过了其余配置:

Below I put the http and endpoint configuration for the token request for your reference. I skip the rest of configuration for keeping the post easy to read:

<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示例应用程序)配置中也发生了同样的问题,这非常相似.可以在

I also assume that the same issue also occurs in the original sparklr application (which is spring oauth2 sample app) configuration for token request which is very similar. That can be found in https://github.com/spring-projects/spring-security-oauth/blob/master/samples/oauth2/sparklr/src/main/webapp/WEB-INF/spring-servlet.xml, and the related part is below:

<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安全性进行更适当的交互,而不必进行不必要的误导性配置,这使我认为我可能错过了一些东西.由于安全是一个敏感的方面,因此我想与您分享一下,并询问我的结论是否正确.

I would expect spring oauth2 to more appropriately interact with spring security instead of having to put unnecessary and misleading configuration, and that makes me think that I may have missed something. Since security is a sensitive aspect I wanted to share that with you and ask if my conclusion correct.

推荐答案

/oauth/token提供了两种不同的方式来认证请求令牌的客户端:

The /oauth/token provides two different ways to authenticate clients which are requesting tokens:

  • 使用HTTP基本身份验证(当存在"http-basic"元素时)

  • Using HTTP-Basic authentication (when "http-basic" element is present)

使用org.springframework.security.web.authentication.www.BasicAuthenticationFilter处理身份验证,并处理"Authorization" HTTP标头,该标头包含客户端的base64编码的凭证.仅当存在Authorization标头时,过滤器才执行处理.始终首先尝试此方法.仅当用户提供了带有无效内容的"Authorization"标头时,才会调用在http-basic上定义的入口点-这就是为什么您看不到调试器中调用的入口点,请尝试设置Authorization HTTP标头和断点的原因会受到打击.

The authentication is handled with org.springframework.security.web.authentication.www.BasicAuthenticationFilter and processes the "Authorization" HTTP header which contains base64 encoded credentials of the client. The filter only performs processing when the Authorization header is present. This method is always tried first. The entry point defined on http-basic will only be invoked when user has supplied an "Authorization" header with invalid content - that's why you don't see the entry point invoked in your debugger, try to set an Authorization HTTP header and your breakpoint will get a hit.

根据OAuth标准中使用client_id和client_secret HTTP参数表的定义

As defined in the OAuth standard using client_id and client_secret HTTP paremeters

这是使用org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter处理的,默认情况下使用入口点将WWW-Authenticate标头发送回客户端.可以自定义默认入口点(有一个setAuthenticationEntryPoint方法).入口点仅在提供client_id参数时使用.

This is handled using org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter and by default uses entry point which sends back WWW-Authenticate header to the client. The default entry point can be customized (there's a setAuthenticationEntryPoint method). The entry point is only used when you supply client_id parameter.

这两种方法都使用不同的方法来获取客户端的用户名和密码,但要使用同一身份验证管理器对其进行验证.

Both of these methods use different ways to obtain client's username+password, but verify it against the same authentication manager.

取出< http-basic>时观察到的无法建立AuthenticationEntryPoint"错误.元素来自Spring Security本身,而不是来自OAuth扩展.原因是Spring Security不能告诉您在定制过滤器ClientCredentialsTokenEndpointFilter内部已经配置了一个默认入口点.而且,Spring Security的HTTP配置始终必须至少具有一个可用的入口点.

The "No AuthenticationEntryPoint could be established" error which you observe when taking out the <http-basic> element is coming from Spring Security itself, not from the OAuth Extension. The reason is that Spring Security is not able to tell that there's a default entry point already configured inside of the custom filter ClientCredentialsTokenEndpointFilter. And the HTTP configuration of Spring Security always must have at least one entry point available.

因此,完整的逻辑如下:

So, the complete logic goes as follows:

  • 当您添加带有无效凭据和< http-basic>的授权"标头时元素存在时,系统将使用在< http-basic>上定义的入口点.元素.如果未指定任何属性(缺少属性入口点引用),系统将自动为您创建并使用BasicAuthenticationEntryPoint的默认实例.
  • 当您使用无效的凭据添加HTTP参数"client_id"和"client_secret"并且存在自定义过滤器clientCredentialsTokenEndpointFilter时,系统将使用在clientCredentialsTokenEndpointFilter bean中定义的入口点(默认情况下为OAuth2AuthenticationEntryPoint实例)
  • 如果既没有"Authorization"标头也不存在"client_id"参数,并且端点要求认证("IS_AUTHENTICATED_FULLY"),则系统将使用在< http entry-point-ref =">中定义的入口点. ,如果存在,则它将使用在http-basic上定义的入口点(如上)
  • 如果您既未指定http-basic(或Spring可以识别的其他默认身份验证方法),也未使用< httpentry-point-ref =">指定默认入口点,则系统将失败,并显示无法建立AuthenticationEntryPoint",因为它需要至少一个入口点,并且不了解clientCredentialsTokenEndpointFilter内部是否有一个入口点.

关于您的观察结果:

>>如果我们指定了基本过滤器,则可以不使用该过滤器,也可以将其删除 端点在http名称空间中.

>> The basic filter is not used and can be removed, if we specify the endpoint in the http namespace instead.

>如果您使用client_id + client_secret对客户进行身份验证,这是正确的

> This is true in case you are authentication your clients using client_id + client_secret

>>在http名称空间中指定基本过滤器或端点是 仅对于编译器停止警告才需要.他们没有 实际使用,并且所使用的端点在内部进行了硬编码 ClientCredentialsTokenEndpointFilter.

>> Specifying either a basic filter,or an endpoint in http namespace is needed only for the compiler to stop the warning. They have no practical use, and the endpoint used is hardcoded inside ClientCredentialsTokenEndpointFilter.

>部分正确,因为将在缺少client_id的情况下使用入口点.

> Partly true, as the entry point will be used in case client_id is missing.

配置确实令人困惑(部分原因是OAuth不是Spring Security的本机部分,而是扩展名),但是所有这些设置都是有意义的,并在特定情况下使用.

The configuration is indeed confusing (which is partly caused by the fact that OAuth isn't a native part of Spring Security, but an extension), but all of those settings make sense and are used in specific situations.

您所做的更改没有安全隐患.

The changes you made have no security implications.

这篇关于Spring oauth2令牌请求中未实际使用的基本身份验证过滤器和身份验证入口点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆