【Spring Security OAuth2】客戶端授權模式(client credentials)~授權服務配置

本文以最簡配置搭建一個授權服務,讓大家初步瞭解授權服務及相關表。
token 存於數據庫中
例子基於Spring Boot 2.1.7.RELEASE ,使用mysql數據庫

參考資源: Authorization Server Configuration

  • 添加一個實現了AuthorizationServerConfigurer接口的實現類且使用@EnableAuthorizationServer註解進行標註

AuthorizationServerConfigurer接口的實現類是AuthorizationServerConfigurerAdapter ,這裏我們繼承AuthorizationServerConfigurerAdapter

/**
 * Created by liuquan on 2019/8/11.
 */
@Configuration
@EnableAuthorizationServer
public class CustomAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

    }
}

@EnableAuthorizationServer註解會導入兩個配置類AuthorizationServerEndpointsConfigurationAuthorizationServerSecurityConfiguration

  • 我們來看看AuthorizationServerEndpointsConfiguration這個配置類在這裏插入圖片描述
    init()會調用AuthorizationServerConfigurer接口中的configure(AuthorizationServerEndpointsConfigurer endpoints)方法,稍後我們將重寫該方法
    在這裏插入圖片描述
    這裏可以看出,如果我們沒有爲AuthorizationServerEndpointsConfigurer設置tokenService屬性,則默認使用DefaultTokenServices
    在這裏插入圖片描述
    從上圖可以看到DefaultTokenServices中設置了TokenStore對象,那TokenStore是做什麼用的呢?

Persistence interface for OAuth2 tokens.

從代碼中的註釋可以知道TokenStore是:OAuth2 令牌的持久化接口。其實現類有多個,如下圖:
在這裏插入圖片描述
在這裏插入圖片描述
如果沒有爲AuthorizationServerEndpointsConfigurer對象設置tokenStore屬性,則默認採用JwtTokenStoreInMemoryTokenStore,本例子採用數據庫存儲token,故重寫AuthorizationServerConfigurer接口中的configure(AuthorizationServerEndpointsConfigurer endpoints)方法設置tokenStore

@Configuration
@EnableAuthorizationServer
public class CustomAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Bean
    public TokenStore tokenStore(){
        return new JdbcTokenStore(dataSource);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore());
    }
}
  • 我們來看看AuthorizationServerSecurityConfiguration這個配置類
    在這裏插入圖片描述
    圖上兩個方法會調用AuthorizationServerConfigurer接口中的configure(ClientDetailsServiceConfigurer clients)方法和configure(AuthorizationServerSecurityConfigurer security)方法,稍後我們將重寫這兩個方法
  • 我們來看看ClientDetailsServiceConfiguration這個配置類
    在這裏插入圖片描述
    35行,創建一個ClientDetailServiceBuilder對象並通過構造函數傳入ClientDetailServiceConfigurer對象,最終ClientDetailsServiceBuilder對象是存入到SecurityConfigurerAdapter類的securityBuilder屬性中
    ClientDetailsServiceConfigurerSecurityConfigurerAdapter的子類,故46行中configurer.and()得到的是securityBuilder屬性,也就是35行存入的ClientDetailsServiceBuilder對象
    在這裏插入圖片描述
    46行的configurer.and().build()實際調用的是ClientDetailsServiceBuilder.build()
    在這裏插入圖片描述
    上圖中的82行拋出一個異常,也就是說我們不能直接使用ClientDetailsServiceBuilder對象,那應該使用哪個對象呢?
    在這裏插入圖片描述
    ClientDetailsServiceBuilder有兩個子類,這裏我們使用JdbcClientDetailsServiceBuilder
    既然已經確定了替代類,那如何改變ClientDetailsServiceConfigurer對象中的builder對象呢
    這時候就可以通過重寫AuthorizationServerConfigurer接口中的configure(ClientDetailsServiceConfigurer clients)方法來改變builder對象
/**
 * Created by liuquan on 2019/8/11.
 */
@Configuration
@EnableAuthorizationServer
public class CustomAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }
}

注:以上只是解決方式之一,還有其它方式可以解決相同問題

  • 我們來看看AuthorizationServerSecurityConfigurer這個配置類
    在這裏插入圖片描述
    AuthorizationServerSecurityConfigurer對象中需要注入一個PasswordEncoder,通過重寫AuthorizationServerConfigurer接口中的configure(AuthorizationServerSecurityConfigurer security)方法來實現
/**
 * Created by liuquan on 2019/8/11.
 */
@Configuration
@EnableAuthorizationServer
public class CustomAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new CustomPasswordEncoder();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("permitAll()")
                .passwordEncoder(passwordEncoder());//若不設置會報錯
    }
}

至此,授權服務最簡配置完成。
此處涉及三張表分別是oauth_client_detailsoauth_access_tokenoauth_refresh_token,Spring Security OAuth2提供了表結構
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
這裏提供mysql版本

DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
  `client_id` varchar(255) NOT NULL,
  `resource_ids` varchar(255) DEFAULT NULL,
  `client_secret` varchar(255) DEFAULT NULL,
  `scope` varchar(255) DEFAULT NULL,
  `authorized_grant_types` varchar(255) DEFAULT NULL,
  `web_server_redirect_uri` varchar(255) DEFAULT NULL,
  `authorities` varchar(255) DEFAULT NULL,
  `access_token_validity` int(11) DEFAULT NULL,
  `refresh_token_validity` int(11) DEFAULT NULL,
  `additional_information` text,
  `autoapprove` varchar(255) DEFAULT 'false',
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `oauth_access_token`;
CREATE TABLE `oauth_access_token` (
  `token_id` varchar(255) DEFAULT NULL,
  `token` blob,
  `authentication_id` varchar(255) DEFAULT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  `client_id` varchar(255) DEFAULT NULL,
  `authentication` blob,
  `refresh_token` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `oauth_refresh_token`;
CREATE TABLE `oauth_refresh_token` (
  `token_id` varchar(255) DEFAULT NULL,
  `token` blob,
  `authentication` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

相應的類爲:JdbcClientDetailsServiceJdbcTokenStore
oauth_client_details需要我們初始化

INSERT INTO `oauth_client_details` VALUES ('app', null, 'app', 'all', 'authorization_code,refresh_token,password,client_credentials', '', 'ADMIN', '60', '60', null, 'false');

oauth_client_details.resource_ids 爲空可訪問全部資源,多個資源ID用[,]分隔,限制可訪問的資源
oauth_client_details.authorized_grant_types 可選值:
authorization_codeclient_credentialsimplicitrefresh_tokenpassword
在這裏插入圖片描述
在這裏插入圖片描述

  • Postman 獲取 Token
    在這裏插入圖片描述
    在這裏插入圖片描述
    請求結果
    在這裏插入圖片描述

demo:spring-security-oauth2-authorization-server

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章