OAuth 2 開發人員指南(Spring security oauth2)

jopen 10年前發布 | 321K 次閱讀 OAuth 2 安全相關

入門

這是支持OAuth2.0的用戶指南。對于OAuth1.0,一切都是不同的,所以看它的用戶指南

本用戶指南分為兩個部分,第一部分是OAuth2.0提供端(OAuth 2.0 Provider),第二部分是OAuth2.0的客戶端(OAuth 2.0 Client)

OAuth2.0提供端

OAuth2.0的提供端的用途是負責將受保護的資源暴露出去。配置包括建立一個可以訪問受保護的資源的客戶端代表。提供端是通過管理和驗證可用于訪問受保護的資源的OAuth 2令牌來做的。在適當的地方,提供端也必須為用戶提供一個用于確認客戶端 是否能夠訪問受保護的資源的接口(也就是一個頁面或是一個窗口)。

在 OAuth 2 提供者其實是分成授權服務和資源服務兩個角色的,而這兩個角色有時是存在于同一個應用程序中的,通過 Spring Security OAuth 你可以有選擇的將它們分裂到兩個應用程序中,也可以有選擇的給授權服務配置多個資源服務。獲取令牌(Tokens)的請求是由Spring MVC的控制器端點來處理的,訪問受保護的資源是通過標準的Spring Security請求過濾器來處理的。

下面列舉的端點是 Spring Security 過濾器鏈實現 OAuth 2 授權服務器必須的端點:

  • AuthorizationEndpoint  是用于授權服務請求的。默認的URL是:/oauth/authrize。

    </li>

  • TokenEndpoint  是用于獲取訪問令牌(Access Tokens)的請求。默認的URL是:/oauth/token。

    </li> </ul>

    下面過濾器是實現一個OAuth2資源服務器所必須的:

    • OAuth2AuthenticationProcessingFilter 這個過濾器是用于加載請求提供的一個授權了的訪問令牌是否有效。

      </li> </ul>

      對于所有的OAuth 2.0的提供端,通過使用Spring OAuth專門的@Configuration適配器來簡化配置。也可以通過XML命名空間來配置OAuth,XML的schema存在:http://www.springframework.org/schema/security/spring-security-oauth2.xsd。命令空間是http://www.springframework.org/schema/security/oauth2

      授權服務器配置

      配置授權服務器時,您必須考慮的grant類型,從終端用戶那,客戶端會使用獲取到的訪問令牌(如授權代碼、用戶憑證、刷新令牌)。服務器的配置是用于提供一些實現,像客戶端細節服務和令牌服務還有啟用或禁用某些方面的全球機制。但是請注意,每個客戶端可以專門配置權限能夠使用某些授權機制和訪問授權。即僅僅因為您的提供者配置為支持“客戶證書”grant類型,并不意味著一個特定的客戶端被授權使用grant類型。

      @EnableAuthorizationServer 注釋用于配置 OAuth 2.0 授權服務器機制,加上任意一個@Beans 去實現 AuthorizationServerConfigurer (這是一個hander適配器實現的空方法)。以下功能委托給由 spring 創造的獨立 configurers 而且傳遞到 AuthorizationServerConfigurer:

      • ClientDetailsServiceConfigurer:這個configurer定義了客戶端細節服務。客戶詳細信息可以被初始化,或者你可以參考現有的商店。

        </li>

      • AuthorizationServerSecurityConfigurer:在令牌端點上定義了安全約束。

        </li>

      • AuthorizationServerEndpointsConfigurer:定義了授權和令牌端點和令牌服務

        </li> </ul>

        提供端配置中重要的一項是提供給OAuth 客戶端的授權碼。 OAuth 客戶端通過將終端用戶導向一個可以輸入證書/口令的授權驗證頁面來獲取授權碼,然后,將授權碼傳遞給提供端授權服務器,服務器驗證后重定向頁面。 在 OAuth 2 說明文檔中有詳細的示例。

        在 xml 配置文件中,可以使用<authorization-server/>節點配置 OAuth 2.0 授權服務器。

        配置客戶端詳細步驟

        ClientDetailsServiceConfigurer 類(AuthorizationServerConfigurer類中的一個調用類)可以用來定義一個基于內存的或者JDBC的客戶端信息服務。 

        客戶端對象重要的屬性有:

        • clientId:(必須)客戶端id。

          </li>

        • secret:(對于可信任的客戶端是必須的)客戶端的私密信息。

          </li>

        • scope:客戶端的作用域。如果scope未定義或者為空(默認值),則客戶端作用域不受限制。

          </li>

        • authorizedGrantTypes:授權給客戶端使用的權限類型。默認值為空。

          </li>

        • authorities:授權給客戶端的權限(Spring普通的安全權限)。

          </li> </ul>

          在運行的應用中,可以通過直接訪問隱藏的存儲文件(如:JdbcClientDetailsService中用到的數據庫表)或者通過實現ClientDetailsManager 接口(也可以實現ClientDetailsService 接口,或者實現兩個接口)來更新客戶端信息。

          管理令牌

          AuthorizationServerTokenServices 接口里定義了 OAuth 2.0 令牌的操作方法。 注意以下幾點:

          • 創建一個訪問令牌時,必須保存權限信息,這樣后續令牌才可以引用它。

            </li>

          • 訪問令牌用于加載創建令牌時的授權信息。

            </li> </ul>

            創建AuthorizationServerTokenServices 接口的實現類時,你可以考慮使用DefaultTokenServices 類,它使用隨機值創建令牌,并處理除永久令牌以外的所有令牌,對于永久令牌,它委托TokenStore類進行處理。 令牌默認采用基于內存實現的存儲方式,但也有一些其它的存儲方式。 下面是其中一些方式的簡介:

            • 默認的InMemoryTokenStore 處理類對于單服務器場景非常適用(優點有:低阻塞,宕機時無需熱切換到備份服務器)。大部分項目可以在開始時或者在開發模式下使用這種方式,這樣比較容易啟動一個沒有其它依賴的服務器。

              </li>

            • JdbcTokenStore 類是實現存儲令牌的JDBC 版本,它將令牌信息保存到關系型數據庫中。 如果服務器間共享數據庫或者同一個服務器有多個實例或者授權服務器、資源服務器有多個組件,那么可以使用JDBC方式存儲令牌。 使用JdbcTokenStore 類時,需要將spring-jdbc組件jar包添加到工程的編譯路徑中。

              </li>

            • JSON網頁令牌(JWT)可以加密所有令牌授權訪問的數據(因此不需要在后臺存儲數據,這就是JWT一個重要的優點)。 缺點是你不能方便地撤銷一個已授權的令牌(因此一般它們被授權的有效期較短,撤銷授權的操作在刷新令牌中進行)。 另一個缺點是存儲的令牌數據會越來越大因為在令牌里面存儲了大量的用戶證書信息。 JwtTokenStore 類不是一個真正的存儲類,它未持久化(保存)任何數據,但是它在傳輸令牌信息和授權信息(在DefaultTokenServices類中實現)中扮演了同樣的角色。 JwtTokenStore(接口)類依賴JwtAccessTokenConverter類,授權服務器和資源服務器都需要接口的實現類(因此他們可以安全地使用相同的數據并進行解碼)。 令牌以默認方式進行簽名,資源服務器為了能夠驗證這些簽名,它需要有與授權服務器相同的對稱密鑰(服務器共享對稱密鑰),或者它需要有可以匹配簽名私鑰的公鑰(公有私有密鑰或混合密鑰)。 為了使用JwtTokenStore 類,你需要在工程編譯路徑下添加spring-security-jwt組件jar包(你可以在Spring OAuthgithub資源庫中找到,但是兩者的版本號是不一致的)。

              </li> </ul>

              Grant 類型

              AuthorizationEndpoint 通過 AuthorizationServerEndpointsConfigurer 可以配置支持 Grant 類型。默認情況下支持所有的 grant 類型,除了密碼(有關詳細信息,請參閱下面的信息如何開啟和關閉)。以下屬性影響grant類型:
                  ? authenticationManager:密碼授予被注入一個authenticationManager開啟。
                  ? authorizationCodeServices:為了身份驗證代碼授予定義了授權代碼服務(org.springframework.security.oauth2.provider.code.AuthorizationCodeServices實例).
                  ? implicitGrantService:在隱式授予管理狀態。
                  ? tokenGranter:TokenGranter(完全掌控的授予和忽略上面的其他屬性)?在XML grant類型包括authorization-server的子元素。

              配置端點的URL

              AuthorizationServerEndpointsConfigurer有一個pathMapping()方法。該方法有兩個參數:

              • defaultPath 默認的端點URL

                </li>

              • customPath 自定義的URL 

                </li> </ul>

                框架自己提供的URL路徑是/oauth/authorize(授權端),/oauth/token (令牌端),/oauth/confirm_access (用戶發送確認授權到這里),還有/oauth/error (用戶呈現授權服務器授權出錯的請求)。

                注意:授權端/oauth/authorize(或者是它的影射)應該是受Spring Security保護的,所以它只能被已授權的用戶訪問。令牌端默認是通過使用支持使用HTTP基本身份驗證客戶機的秘密的注解@Configuration,被Spring Oauth保護的,但不是使用XML文件的(所以在這種情況下它被保護是很明確的)。

                使用XML的<authorization-server/>元素可以使用一些屬性來達到改變默認的端點URL。


                自定義錯誤處理

                授權服務器上錯誤處理使用標準的 Spring MVC 功能,即 @ExceptionHandler 端點本身的方法。用戶還可以提供一個 WebResponseExceptionTranslator 端點本身,最好的辦法是改變響應的內容而不是他們呈現的方式。異常的呈現代表 HttpMesssageConverters (這個可以添加到MVC的配置中)令牌的端點和OAuth的錯誤視圖(/ OAuth /error)的授權端點。提供一個whitelabel錯誤端點,但是用戶可能需要提供一個自定義的實現(例如,就添加一個 @Controller,它的請求映射是 @RequestMapping(“/ oauth /error”))。

                配置資源服務器

                資源服務器(可能和授權服務器或者一個單獨的應用程序在同一臺主機上)提供被OAuth2 令牌保護的資源。 Spring OAuth提供一個Spring Security授權過濾器,它實現保護資源的功能。在@Configuration類中,你可以使用@EnableResourceServer來開啟/關閉過濾器,使用ResourceServerConfigurer來配置它。 下面是可配置的屬性:

                • tokenServices:定義令牌服務的實體(ResourceServerTokenServices類的實例)。

                  </li>

                • resourceId:資源ID(可選的,建議配置,如果不為空,授權服務器會對它進行驗證)。

                  </li> </ul>

                  @EnableResourceServer注解把一個 OAuth2AuthenticationProcessingFilter 類型過濾器添加到Spring Security 過濾鏈中。

                  在 XML中,有一個<resource-server/>元素,它有一個id屬性 – 這是servlet過濾器的bean id,它過濾哪些可以被添加到Spring Security鏈中。

                  配置OAuth-Aware表達式處理器

                  你可能想要使用Spring Security的使用表達式語言配置訪問控制的優點。 表達式處理器在 @EnableResourceServer配置中以默認方式進行注冊。 表達式包括#oauth2.clientHasRole,#oauth2.clientHasAnyRole, 和 #oath2.denyClient,這些可以提供基于oauth客戶端角色的訪問控制(詳細列表見OAuth2SecurityExpressionMethods)。 在XML中,你可以在<http/> 安全配置節點內使用expression-handler元素注冊一個oauth-aware表達式處理器。

                  OAuth 2.0 客戶端

                  OAuth 2.0 客戶端控制著 OAuth 2.0保護的其它服務器的資源的訪問權限。 配置包括建立相關受保護資源與有權限訪問資源的用戶之間的連接。 客戶端也需要實現存儲用戶的授權代碼和訪問令牌的功能。

                  受保護資源的配置

                  受保護的資源(或稱為遠程資源)可以使用OAuth2ProtectedResourceDetails類型的實體bean定義。 一個受保護的資源有以下屬性:

                  • id:資源id。它僅在客戶端搜索資源的時候使用;在OAuth協議中它從未被用到。它也被用作bean的id。

                    </li>

                  • clientId:OAuth客戶端id。OAuth提供端依賴這個id來識別客戶端。

                    </li>

                  • clientSecret:與資源有關的秘密。默認情況下,該值不為空。

                    </li>

                  • accessTokenUri:提供訪問口令的OAuth提供者終端的統一資源標識符(URI)。

                    </li>

                  • scope:以逗號分隔的字符串列表,標識可訪問資源的范圍。默認情況下,該值為空。

                    </li>

                  • clientAuthenticationScheme: 客戶端對訪問的令牌終端授權時使用的機制。 建議值: "http_basic" 和 "form"。 默認值: "http_basic"。 見OAuth 2 幫助文檔2.1節。

                    </li> </ul>

                    不同的授權類型有不同的實現OAuth2ProtectedResourceDetails (對于client_credentials授權類型,使用ClientCredentialsResource )的方式。對于需要進行用戶身份驗證的授權類型,還有一個屬性:

                    • userAuthorizationUri: 用戶訪問資源需要身份驗證時跳轉頁面的URI。 注意這個字段不是必填的,它依賴于被支持的OAuth 2的配置文件類型。

                      </li> </ul>

                      在XML中,可以使用<resource/>元素創建一個OAuth2ProtectedResourceDetails類型的實體bean。 它有上面提到的所有的屬性。

                      使用@EnableOAuth2Client對OAuth2.0的客戶端的配置比較簡單。主要要做兩件事情:

                      • 創建一個過濾bean(用oauth2ClientContextFilter)來存儲當前的請求和上下文。在這種情況下需要在請求期間授權,來管理從重定向的位置和OAuth已認證的url

                        </li>

                      • 在請求作用域中創建一個AccessTokenRequest類型的bean。這個類型的bean可以在個人用戶的沖突中被識別碼識別(或隱式的),授權客戶端保持授權狀態。

                        </li> </ul>

                        這個過濾器需要能夠連接到應用(例如,使用Servlet初始化程序或者web.xml配置文件配置 一個和DelegatingFilterProxy相同名稱的代理)。


                        在一個OAuth2RestTemplate中AccessTokenRequest可以這樣使用:

                        @Autowired
                        private OAuth2ClientContext oauth2Context;

                        @Bean public OAuth2RestTemplate sparklrRestTemplate() {     return new OAuth2RestTemplate(sparklr(), oauth2Context); }</pre>

                        OAuth2ClientContext可以在Session的作用域中保持不同用戶不同的狀態。如果沒有這個功能,你需要在你自己的服務強上管理等效的數據結構,映射不用用戶進來的請求并且用相互隔離的OAuth2ClientContext實例連接各個用戶。

                        在XML文件中,有一個帶有id屬性的<client/>標簽用于表示servlet的Filter的bean id,這個必須映射成一個和DelegatingFilterProxy有相同名稱的@Configuration注解。


                        訪問受保護的資源

                        一旦,你已經提供了所有的資源服務器配置時,現在你可以訪問這些資源。建議的訪問這些資源是通過使用在Spring3中提到的RestTemplate。Spring Security OAuth已經提供了一個擴展的RestTemplate,只需要提供一個OAuth2ProtectedResourceDetails的實例。使用它與user-tokens(授權代碼授予)你應該考慮使用@EnableOAuth2Client配置(或XML等價< oauth:rest-template / >),造成了一些請求和會話作用域上下文對象,要求不同的用戶在運行時不發生沖突。

                        客戶端持久化訪問令牌

                        客戶端不需要持久化令牌,但是它可以很好的用戶不需要批準一個新的令牌格蘭特每次重新啟動客戶機應用程序。ClientTokenServices接口定義所需的操作持續OAuth 2.0為特定用戶令牌。提供一個JDBC實現,但是如果你喜歡的話你可以實現自己的服務以存儲的訪問令牌持久數據庫和相關的驗證實例。如果你想使用此功能,你需要提供一個專門配置TokenProvider theOAuth2RestTemplate如

                        @Bean@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)public OAuth2RestOperations restTemplate() {
                            OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(accessTokenRequest));
                            AccessTokenProviderChain provider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider()));
                            provider.setClientTokenServices(clientTokenServices());
                            return template;}




                        為外部 OAuth2 提供者定制客戶端

                        一些外部OAuth2提供商(如非死book)不完全實現正確規范,否則他們只是困在一個舊版本比Spring Security OAuth的規范。在您的客戶機應用程序使用這些供應商可能需要適應客戶端基礎設施的各個部分。

                        使用非死book作為一個例子,有一個非死book功能tonr2應用程序(您需要更改配置添加你自己的,有效的,客戶機id和秘密,他們很容易生成在非死book網站上)。

                        非死book響應令牌也包含一個不一致的、有失效時間的JSON實體(他們使用到期而不是expires_in),所以如果你想在應用程序中使用失效時間你將不得不使用一個自定義OAuth2SerializationService手動解碼。


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!