oauth2.0通過JdbcClientDetailsService從數據庫讀取相應的配置
在上一節我們講述的配置是把授權碼存儲在redis中,把相應的請求的路徑用使用in-memory存儲 ,這個是放在了內存中,但是實際開發我們的數據希望是從數據表中查詢的,那應該怎么做呢?
1.回顧in-memory存儲
/**
* inMemory是存儲到內存中 並未到數據庫
*/
clients.inMemory() //client Id .withClient("normal-app") .authorizedGrantTypes("authorization_code", "implicit") .authorities("ROLE_CLIENT") .scopes("read","write") .resourceIds(resourceId) .accessTokenValiditySeconds(accessTokenValiditySeconds)//授權碼存活時間 .and() .withClient("trusted-app") .authorizedGrantTypes("client_credentials", "password") .authorities("ROLE_TRUSTED_CLIENT") .scopes("read", "write") .resourceIds(resourceId) .accessTokenValiditySeconds(accessTokenValiditySeconds) .secret("secret");
如果使用的是這種方式,我們對應的授權碼的請求路徑如下:
http://localhost:8787/oauth/authorize?client_id=normal-app&response_type=code&scope=read&redirect_uri=/resources/user
相應的參數請對照上
然后我們使用的是jwt的令牌方式,相應的請求路徑如下:
http://localhost:8787/oauth/token?code=r8YBUL&grant_type=authorization_code&client_id=normal-app&redirect_uri=/resources/user
這個是放在內存中的存儲方式
2.如果我需要從數據庫讀取相應的字段的參數 可如下配置:
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //默認值InMemoryTokenStore對於單個服務器是完全正常的(即,在發生故障的情況下,低流量和熱備份備份服務器)。大多數項目可以從這里開始,也可以在開發模式下運行,以便輕松啟動沒有依賴關系的服務器。 //這JdbcTokenStore是同一件事的JDBC版本,它將令牌數據存儲在關系數據庫中。如果您可以在服務器之間共享數據庫,則可以使用JDBC版本,如果只有一個,則擴展同一服務器的實例,或者如果有多個組件,則授權和資源服務器。要使用JdbcTokenStore你需要“spring-jdbc”的類路徑。 //這個地方指的是從jdbc查出數據來存儲 clients.withClientDetails(clientDetails()); }
這里可以看到我們是把之前的從內存讀取的方式給去掉了,取而代之的是clientDetails()這個方法,然后我們看下這個方法:
@Bean
public ClientDetailsService clientDetails() { return new JdbcClientDetailsService(dataSource); }
只需配置這個bean即可 但是我們的datasource是在yml配置文件中配置好了的,只需要注入:
import javax.sql.DataSource; @Resource private DataSource dataSource;
使用DataSource注解需要引入依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
但是這里還沒完,我們首先要講下JdbcClientDetailsService是如何從數據庫讀取的,我們可以點擊進入查看相應的源碼,如下所示:
public JdbcClientDetailsService(DataSource dataSource) { this.updateClientDetailsSql = DEFAULT_UPDATE_STATEMENT; this.updateClientSecretSql = "update oauth_client_details set client_secret = ? where client_id = ?"; this.insertClientDetailsSql = "insert into oauth_client_details (client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, client_id) values (?,?,?,?,?,?,?,?,?,?,?)"; this.selectClientDetailsSql = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?"; this.passwordEncoder = NoOpPasswordEncoder.getInstance(); Assert.notNull(dataSource, "DataSource required"); this.jdbcTemplate = new JdbcTemplate(dataSource); this.listFactory = new DefaultJdbcListFactory(new NamedParameterJdbcTemplate(this.jdbcTemplate)); }
我們可以看到,他自己是有一個默認的字段的表的,里面有相應的查詢的方法,所以我們需要建立一個這樣的表,sql如下:
-- ---------------------------- -- Table structure for oauth_client_details 將請求的路徑存在數據表 -- ---------------------------- DROP TABLE IF EXISTS `oauth_client_details`; CREATE TABLE `oauth_client_details` ( `client_id` varchar(48) NOT NULL, `resource_ids` varchar(256) DEFAULT NULL, `client_secret` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `authorized_grant_types` varchar(256) DEFAULT NULL, `web_server_redirect_uri` varchar(256) DEFAULT NULL, `authorities` varchar(256) DEFAULT NULL, `access_token_validity` int(11) DEFAULT NULL, `refresh_token_validity` int(11) DEFAULT NULL, `additional_information` varchar(4096) DEFAULT NULL, `autoapprove` varchar(256) DEFAULT NULL, PRIMARY KEY (`client_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
這個是默認的類的表,一般用它默認的即可,我們這邊就需要根據以上的字段配置相關的內容,如下:

image.png
這里配置好了之后我們的訪問路徑為:
//步驟:客戶端向認證服務器申請令牌
http://localhost:8787/oauth/token?client_id=normal-app&grant_type=authorization_code&code=1oCj8e&redirect_uri=http://localhost:8787/resources/user
然后令牌的訪問路徑為:
//拿到令牌后訪問資源:
http://localhost:8787/resources/user?access_token=9d62c7b0-780e-4c6a-ad5a-56d79a089342
記得code要換成上一步生成的code