OAuth2 客戶端模式


5. 客戶端模式

客戶端模式,指客戶端以自己的名義,而不是以用戶的名義,向授權服務器進行認證。

嚴格地說,客戶端模式並不屬於 OAuth 框架所要解決的問題。在這種模式中,用戶直接向客戶端注冊,客戶端以自己的名義要求授權服務器提供服務,其實不存在授權問題。

  旁白君:我們對接微信公眾號時,就采用的客戶端模式。我們的后端服務器就扮演“客戶端”的角色,與微信公眾號的后端服務器進行交互。

 

 

  • (A)客戶端向授權服務器進行身份認證,並要求一個訪問令牌
  • (B)授權服務器確認無誤后,向客戶端提供訪問令牌。

下面,我們來新建兩個項目,搭建一個客戶端模式的使用示例。如下圖所示:

 

 

5.1 搭建授權服務器

復制出 lab-68-demo02-authorization-server-with-client-credentials 項目,修改搭建授權服務器。改動點如下圖所示:

 

 

 

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    /**
     * 用戶認證 Manager
     */
    @Autowired
    private AuthenticationManager authenticationManager;

    //配置使用的 AuthenticationManager 實現用戶認證的功能
    @Bean
    public static NoOpPasswordEncoder passwordEncodeF(){

        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }

    //設置 /oauth/check_token 端點,通過認證后可訪問。
    //這里的認證,指的是使用 client-id + client-secret 進行的客戶端認證,不要和用戶認證混淆。
    //其中,/oauth/check_token 端點對應 CheckTokenEndpoint 類,用於校驗訪問令牌的有效性。
    //在客戶端訪問資源服務器時,會在請求中帶上訪問令牌。
    //在資源服務器收到客戶端的請求時,會使用請求中的訪問令牌,找授權服務器確認該訪問令牌的有效性。
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.checkTokenAccess("isAuthenticated()");
    }

    //進行 Client 客戶端的配置。
    //設置使用基於內存的 Client 存儲器。實際情況下,最好放入數據庫中,方便管理。
/*
*
* 創建一個 Client 配置。如果要繼續添加另外的 Client 配置,可以在 <4.3> 處使用 #and() 方法繼續拼接。
* 注意,這里的 .withClient("clientapp").secret("112233") 代碼段,就是 client-id 和 client-secret。
*補充知識:可能會有胖友會問,為什么要創建 Client 的 client-id 和 client-secret 呢?
*通過 client-id 編號和 client-secret,授權服務器可以知道調用的來源以及正確性。這樣,
*即使“壞人”拿到 Access Token ,但是沒有 client-id 編號和 client-secret,也不能和授權服務器發生有效的交互。
*/
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory() // <4.1>
                .withClient("clientapp").secret("112233") // <4.2> Client 賬號、密碼。
                .authorizedGrantTypes("client_credentials") // <4.2> 客戶端模式
                .redirectUris("http://127.0.0.1:9090/callback02")
                .scopes("read_userinfo", "read_contacts") // <4.2> 可授權的 Scope
//                .and().withClient() // <4.3> 可以繼續配置新的 Client
        ;
    }

}

  

① 刪除 SecurityConfig 配置類,因為客戶端模式下,無需 Spring Security 提供用戶的認證功能。

    但是,Spring Security OAuth 需要一個 PasswordEncoder Bean,否則會報錯,因此我們在 OAuth2AuthorizationServerConfig 類的 #passwordEncoder() 方法進行創建。

② 修改 OAuth2AuthorizationServerConfig 類,設置使用 "client_credentials" 客戶端模式。

 

5.1.1 簡單測試

執行 AuthorizationServerApplication 啟動授權服務器。下面,我們使用 Postman 模擬一個 Client

① POST 請求 http://localhost:8080/oauth/token 地址,使用客戶端模式進行授權。如下圖所示:

 

 

 

 

請求說明:

  

  • 通過 Basic Auth 的方式,填寫 client-id + client-secret 作為用戶名與密碼,實現 Client 客戶端有效性的認證。
  • 請求參數 grant_type 為 "client_credentials",表示使用客戶端模式

響應就是訪問令牌,胖友自己瞅瞅即可。

 

5.2 搭建資源服務器

復制 lab-68-demo02-resource-server 項目,修改點如下圖所示:

 

 

① 新建 ClientLoginController 類,提供 /client-login 接口,實現調用授權服務器,進行客戶端模式的授權,獲得訪問令牌。代碼如下:

@RestController
@RequestMapping("/")
public class ClientLoginController {

    @Autowired
    private OAuth2ClientProperties oauth2ClientProperties;

    @Value("${security.oauth2.access-token-uri}")
    private String accessTokenUri;

    @PostMapping("/client-login")
    public OAuth2AccessToken login() {
        // 創建 ClientCredentialsResourceDetails 對象
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setAccessTokenUri(accessTokenUri);
        resourceDetails.setClientId(oauth2ClientProperties.getClientId());
        resourceDetails.setClientSecret(oauth2ClientProperties.getClientSecret());
        // 創建 OAuth2RestTemplate 對象
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails);
        restTemplate.setAccessTokenProvider(new ClientCredentialsAccessTokenProvider());
        // 獲取訪問令牌
        return restTemplate.getAccessToken();
    }

}

  

代碼比較簡單,還是使用 OAuth2RestTemplate 進行請求授權服務器,胖友自己瞅瞅哈。

② 在 OAuth2ResourceServerConfig 配置類中,設置 /client-login 接口無需權限驗證,不然無法調用哈。

 

5.2.1 簡單測試

執行 ResourceServerApplication 啟動資源服務器。

① 使用「5.1.1 簡單測試」小節獲得的訪問令牌,請求 <127.0.0.1:9090/api/example/hello> 接口時帶上,則請求會被通過。如下圖所示:

 

 

② 請求 http://127.0.0.1:9090/client-login 接口,使用客戶端模式進行授權,獲得訪問令牌。如下圖所示:

 

 

 

響應結果和授權服務器的 /oauth/token 接口是一致的,因為就是調用它,嘿嘿~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM