簡體   English   中英

基本身份驗證過濾器和身份驗證入口點實際上並未使用spring oauth2令牌請求

[英]Basic Authentication Filter and authentication entry point not actually used from spring oauth2 token request

我已經使用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。請確保您具有通過命名空間配置的登錄機制(例如表單登錄)或指定帶有'entry-point-ref'屬性的自定義AuthenticationEntryPoint”。

下一步,我在http命名空間中添加了entry-point-ref =“clientAuthenticationEntryPoint,並取消了警告。我測試了應用程序並正確播放。

但是,除了上述內容之外,我還在調試期間進行了以下觀察:ClientCredentialsTokenEndpointFilter在私有變量中包含其自己的OAuth2AuthenticationEntryPoint入口點,並在由於錯誤的客戶端憑據而失敗時使用它。 因此,無論在基本過濾器中還是在http命名空間中指定的入口點都無關緊要。 最后,ClientCredentialsTokenEndpointFilter將使用自己的私有OAuth2AuthenticationEntryPoint。 總結一下我的結論似乎如下:

  • 如果我們在http命名空間中指定端點,則不使用基本過濾器並且可以將其刪除。
  • 僅在編譯器停止警告時才需要在http命名空間中指定基本過濾器或端點。 它們沒有實際用途,所使用的端點在ClientCredentialsTokenEndpointFilter中是硬編碼的。

下面我將令牌請求的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進行交互,而不必使用不必要的誤導配置,這讓我覺得我可能錯過了一些東西。 由於安全性是一個敏感方面,我想與您分享,並詢問我的結論是否正確。

/ oauth / token提供了兩種不同的方法來驗證請求令牌的客戶端:

  • 使用HTTP-Basic身份驗證(當存在“http-basic”元素時)

    使用org.springframework.security.web.authentication.www.BasicAuthenticationFilter處理身份驗證,並處理包含客戶端的base64編碼憑據的“Authorization”HTTP標頭。 過濾器僅在存在Authorization標頭時執行處理。 始終首先嘗試此方法。 只有當用戶提供了包含無效內容的“Authorization”標頭時,才會調用http-basic上定義的入口點 - 這就是為什么你沒有看到調試器中調用的入口點,嘗試設置Authorization HTTP標頭和你的斷點會受到打擊。

  • 如OAuth標准中所定義,使用client_id和client_secret HTTP參數

    這是使用org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter處理的,默認情況下使用入口點將WWW-Authenticate標頭發送回客戶端。 可以自定義默認入口點(有一個setAuthenticationEntryPoint方法)。 只有在提供client_id參數時才使用入口點。

這兩種方法都使用不同的方法來獲取客戶端的用戶名+密碼,但是針對同一個身份驗證管理器進行驗證。

在取出<http-basic>元素時,您觀察到的“No AuthenticationEntryPoint可以建立”錯誤來自Spring Security本身,而不是來自OAuth擴展。 原因是Spring Security無法判斷自定義過濾器ClientCredentialsTokenEndpointFilter中是否已配置了默認入口點。 並且Spring Security的HTTP配置始終必須至少有一個入口點可用。

所以,完整的邏輯如下:

  • 當您包含帶有無效憑據的“Authorization”標頭並且存在<http-basic>元素時,系統將使用<http-basic>元素上定義的入口點。 如果未指定(缺少屬性entry-point-ref),系統將自動為您創建BasicAuthenticationEntryPoint的默認實例並使用它。
  • 當您包含帶有無效憑據的HTTP參數“client_id”和“client_secret”並且存在自定義過濾器clientCredentialsTokenEndpointFilter時,系統將使用clientCredentialsTokenEndpointFilter bean中定義的入口點(默認情況下為OAuth2AuthenticationEntryPoint的實例)
  • 如果既沒有“授權”標題也沒有“client_id”參數,並且端點需要認證(“IS_AUTHENTICATED_FULLY”),系統將使用<http entry-point-ref =“”>上定義的入口點(如果存在),否則它將使用http-basic上定義的入口點(如上所述)
  • 如果您既沒有指定http-basic(或Spring識別的其他默認身份驗證方法),也沒有使用<http entry-point-ref =“”>指定默認入口點,系統將失敗,並且“無法建立AuthenticationIntertryPoint” “,因為它需要至少一個入口點,並且它不理解clientCredentialsTokenEndpointFilter中有一個可用的入口點。

關於你的觀察:

>>如果我們在http命名空間中指定端點,則不使用基本過濾器並將其刪除。

>如果您使用client_id + client_secret對客戶端進行身份驗證,則情況屬實

>>僅在編譯器停止警告時才需要在http命名空間中指定基本過濾器或端點。 它們沒有實際用途,所使用的端點在ClientCredentialsTokenEndpointFilter中是硬編碼的。

>部分正確,因為在缺少client_id的情況下將使用入口點。

配置確實令人困惑(部分原因是OAuth不是Spring Security的本機部分,而是擴展),但所有這些設置都有意義並且在特定情況下使用。

您所做的更改不會產生任何安全隱患。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM