Spring Cloud进阶之路 | 十八:授权服务(Spring Cloud Oauth2)ClientDetailsService之JdbcClientDetailsService
前面的文章Spring Cloud进阶之路 | 八:授权服务(Spring Cloud Oauth2)中,介绍了基于Spring Cloud Oauth2框架的微服务授权服务器。其中,关于认证客户端相关信息均存储在内存中,服务一旦重启,即随即丢失,非常不利于维护。在实际项目中,势必要持久化存储。本文即对认证客户端信息持久化ClientDetailsServic之JdbcClientDetailsS
前言
前面的文章Spring Cloud进阶之路 | 八:授权服务(Spring Cloud Oauth2)中,介绍了基于Spring Cloud Oauth2框架的微服务授权服务器。其中,关于认证客户端相关信息均存储在内存中,服务一旦重启,即随即丢失,非常不利于维护。在实际项目中,势必要持久化存储。
本文即对认证客户端信息持久化ClientDetailsServic之JdbcClientDetailsService做相关说明。
准备工作
复用文章Spring Cloud进阶之路 | 八:授权服务(Spring Cloud Oauth2)中的xmall-auth授权工程。
授权服务器配置改造
通过方法public void configure(ClientDetailsServiceConfigurer clients) throws Exception配置ClientDetailsServic为JdbcClientDetailsService。
其中,共有四种方案。下面将分别介绍。
方案一
此方案最简单常见,只需配置DataSource即可,其它交给框架自动配置。
package com.luas.xmall.auth.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.
allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置方法1,只需配置DataSource即可,其它交给框架自动配置
clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
}
}
方案二
本方案以构建ClientDetailsServiceBuilder为最终目的。
package com.luas.xmall.auth.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.
allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置方法2,构建ClientDetailsServiceBuilder
clients.configure(jdbcClientDetailsServiceBuilder());
}
private JdbcClientDetailsServiceBuilder jdbcClientDetailsServiceBuilder() {
return new JdbcClientDetailsServiceBuilder().dataSource(dataSource).passwordEncoder(passwordEncoder);
}
}
方案三
此方案以构建ClientDetailsService为最终目的,本例中,我们使用ClientDetailsServiceBuilder来构建ClientDetailsService,即以JdbcClientDetailsServiceBuilder构建JdbcClientDetailsService,比较方便,也可以直接构建JdbcClientDetailsService对象。
使用JdbcClientDetailsServiceBuilder构建JdbcClientDetailsService。
package com.luas.xmall.auth.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.
allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置方法3,使用ClientDetailsServiceBuilder构建ClientDetailsService
clients.withClientDetails(jdbcClientDetailsService());
}
private ClientDetailsService jdbcClientDetailsService() throws Exception {
return new JdbcClientDetailsServiceBuilder().dataSource(dataSource).passwordEncoder(passwordEncoder).build();
}
}
直接构建JdbcClientDetailsService对象。
package com.luas.xmall.auth.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.
allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置方法3,使用ClientDetailsServiceBuilder构建ClientDetailsService
clients.withClientDetails(jdbcClientDetailsService());
}
private ClientDetailsService jdbcClientDetailsService() throws Exception {
// 直接构建JdbcClientDetailsService对象
JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
return jdbcClientDetailsService;
}
}
方案四
本方案为自定义ClientDetailsService,实际项目中,也许存在不按照官方建议的数据结构的情况,此时,就需要自行定义数据结构,同时,也必须自行定义对应的ClientDetailsService,用以获取ClientDetails。
package com.luas.xmall.auth.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.
allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置方法4,自定义ClientDetailsService
clients.withClientDetails(myClientDetailsService());
}
public ClientDetailsService myClientDetailsService() throws Exception {
return new ClientDetailsService() {
@Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
// TODO 调用dao、service查询自定义数据结构、库,组织对应的ClientDetails
return null;
}
};
}
}
聚合配置
聚合四种方案,配置如下,可自行注释、取消相关注释,以开启对应方案。
package com.luas.xmall.auth.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.
allowFormAuthenticationForClients()
.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()")
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(new InMemoryTokenStore())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 配置方法1,只需配置DataSource即可,其它交给框架自动配置
clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
// 配置方法2,构建ClientDetailsServiceBuilder
//clients.configure(jdbcClientDetailsServiceBuilder());
// 配置方法3,使用ClientDetailsServiceBuilder构建ClientDetailsService
//clients.withClientDetails(jdbcClientDetailsService());
// 配置方法4,自定义ClientDetailsService
//clients.withClientDetails(myClientDetailsService());
}
private JdbcClientDetailsServiceBuilder jdbcClientDetailsServiceBuilder() {
return new JdbcClientDetailsServiceBuilder().dataSource(dataSource).passwordEncoder(passwordEncoder);
}
private ClientDetailsService jdbcClientDetailsService() throws Exception {
return new JdbcClientDetailsServiceBuilder().dataSource(dataSource).passwordEncoder(passwordEncoder).build();
// 直接构建JdbcClientDetailsService对象
// JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
// jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
// return jdbcClientDetailsService;
}
public ClientDetailsService myClientDetailsService() throws Exception {
return new ClientDetailsService() {
@Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
// TODO 调用dao、service查询自定义数据结构、库,组织对应的ClientDetails
return null;
}
};
}
}
数据源
配置数据源DataSource。
server:
port: 7777
spring:
datasource:
name: test
url: jdbc:mysql://127.0.0.1:3306/xmall-auth?characterEncoding=utf8&generateSimpleParameterMetadata=true&serverTimezone=GMT%2B8
username: root
password: 123456
# 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
filters: stat,slf4j
maxActive: 20
initialSize: 2
minIdle: 1
maxWait: 60000
timeBetweenEvictionRunsMillis: 60
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
数据结构
官方建议的数据结构如下,可根据数据库类型,自行调整。shcema.sql文件位于src/main/resources下。
create table oauth_client_details (
client_id VARCHAR(256) PRIMARY KEY,
resource_ids VARCHAR(256),
client_secret VARCHAR(256),
scope VARCHAR(256),
authorized_grant_types VARCHAR(256),
web_server_redirect_uri VARCHAR(256),
authorities VARCHAR(256),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additional_information VARCHAR(4096),
autoapprove VARCHAR(256),
create_time TIMESTAMP
);
create table oauth_client_token (
token_id VARCHAR(256),
token LONGVARBINARY,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256),
create_time TIMESTAMP
);
create table oauth_access_token (
token_id VARCHAR(256),
token LONGVARBINARY,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256),
authentication LONGVARBINARY,
refresh_token VARCHAR(256),
create_time TIMESTAMP
);
create table oauth_refresh_token (
token_id VARCHAR(256),
token LONGVARBINARY,
authentication LONGVARBINARY,
create_time TIMESTAMP
);
create table oauth_code (
code VARCHAR(256), authentication LONGVARBINARY, create_time TIMESTAMP
);
create table oauth_approvals (
userId VARCHAR(256),
clientId VARCHAR(256),
scope VARCHAR(256),
status VARCHAR(10),
expiresAt TIMESTAMP,
lastModifiedAt TIMESTAMP,
create_time TIMESTAMP
);
create table ClientDetails (
appId VARCHAR(256) PRIMARY KEY,
resourceIds VARCHAR(256),
appSecret VARCHAR(256),
scope VARCHAR(256),
grantTypes VARCHAR(256),
redirectUrl VARCHAR(256),
authorities VARCHAR(256),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additionalInformation VARCHAR(4096),
autoApproveScopes VARCHAR(256),
create_time TIMESTAMP
);
另外,针对mysql,笔者改造了一版mysql数据库对应的数据结构,shcema-mysql.sql文件位于src/main/resources下。
create table oauth_client_details (
client_id VARCHAR(255) PRIMARY KEY,
resource_ids VARCHAR(255),
client_secret VARCHAR(255),
scope VARCHAR(255),
authorized_grant_types VARCHAR(255),
web_server_redirect_uri VARCHAR(255),
authorities VARCHAR(255),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additional_information VARCHAR(4096),
autoapprove VARCHAR(255),
create_time TIMESTAMP
);
create table oauth_client_token (
token_id VARCHAR(255),
token BLOB,
authentication_id VARCHAR(255) PRIMARY KEY,
user_name VARCHAR(255),
client_id VARCHAR(255),
create_time TIMESTAMP
);
create table oauth_access_token (
token_id VARCHAR(255),
token BLOB,
authentication_id VARCHAR(255) PRIMARY KEY,
user_name VARCHAR(255),
client_id VARCHAR(255),
authentication BLOB,
refresh_token VARCHAR(255),
create_time TIMESTAMP
);
create table oauth_refresh_token (
token_id VARCHAR(255),
token BLOB,
authentication BLOB,
create_time TIMESTAMP
);
create table oauth_code (
code VARCHAR(255), authentication BLOB, create_time TIMESTAMP
);
create table oauth_approvals (
userId VARCHAR(255),
clientId VARCHAR(255),
scope VARCHAR(255),
status VARCHAR(10),
expiresAt TIMESTAMP,
lastModifiedAt TIMESTAMP,
create_time TIMESTAMP
);
create table ClientDetails (
appId VARCHAR(255) PRIMARY KEY,
resourceIds VARCHAR(255),
appSecret VARCHAR(255),
scope VARCHAR(255),
grantTypes VARCHAR(255),
redirectUrl VARCHAR(255),
authorities VARCHAR(255),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additionalInformation VARCHAR(4096),
autoApproveScopes VARCHAR(255),
create_time TIMESTAMP
);
时间戳字段问题
mysql版本不同,对TIMESTAMP类型解释也不同,如mysql5.7,版本,create_time TIMESTAMP代表的含义如下:
-
如果该字段是第一个TIMESTAMP字段,则等同于create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
-
如果该字段不是第一个TIMESTAMP字段,则等同于create_time TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00'。特别说明一下,此种情况下,数据库会报错,因为不允许0类型的日期值存在。
至于其它版本的解释,读者可自行查阅相关资料,笔者后续也会详细介绍此数据库字段类型。
客户端信息
将之前在内存中存储的客户端信息初始化到数据库中,sql文件见目录src/main/resources/。
INSERT INTO `oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`, `create_time`) VALUES ('admin', 'xmall-auth,xmall-product', '$2a$10$zNDgAkXKu4xSeupcLlZsKuSpmU75MQDqODhieBZvTMdeNEKwaUoIi', 'server,select', 'authorization_code,password,refresh_token,client_credentials,implicit', 'http://www.baidu.com', NULL, NULL, NULL, NULL, NULL, '2020-02-14 17:23:07');
INSERT INTO `oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`, `create_time`) VALUES ('client_1', 'xmall-auth,xmall-product', '$2a$10$zNDgAkXKu4xSeupcLlZsKuSpmU75MQDqODhieBZvTMdeNEKwaUoIi', 'server,select', 'password,refresh_token', NULL, NULL, NULL, NULL, NULL, NULL, '2020-02-14 17:24:17');
INSERT INTO `oauth_client_details`(`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`, `create_time`) VALUES ('client_2', 'xmall-auth,xmall-product', '$2a$10$zNDgAkXKu4xSeupcLlZsKuSpmU75MQDqODhieBZvTMdeNEKwaUoIi', 'server,select', 'client_credentials,refresh_token', NULL, NULL, NULL, NULL, NULL, NULL, '2020-02-14 17:24:57');
验证
启动xmall-auth工程,端口为7777。
访问http://localhost:7777/oauth/token,输入一众参数,诸如client_id、client_secret、grant_type等,点击Send,即出现access_token、refresh_token等信息。
源码
github
https://github.com/liuminglei/SpringCloudLearning/tree/master/18/
gitee
https://gitee.com/xbd521/SpringCloudLearning/tree/master/18/
本文系【银河架构师】原创,如需转载请在文章明显处注明作者及出处。
微信搜索【银河架构师】,发现更多精彩内容。
更多推荐
所有评论(0)