Java 如何在Spring中使用JDBC for ClientDetailsServiceConfigurer添加客户端?
我记忆中的东西工作如下:Java 如何在Spring中使用JDBC for ClientDetailsServiceConfigurer添加客户端?,java,mysql,spring-security-oauth2,Java,Mysql,Spring Security Oauth2,我记忆中的东西工作如下: @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("clientapp") .authorizedGrantTypes("password", "refresh_token")
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("clientapp")
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("123456");
}
clients.jdbc(dataSource).withClient("clientapp")
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("123456").and().build();
我想使用JDBC实现。为此,我创建了以下表(使用MySQL):
我是否需要在MySQL表中手动添加客户机
我试过这个:
clients.jdbc(dataSource).withClient("clientapp")
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("123456");
希望Spring能在好的表格中插入正确的内容,但它似乎没有这样做。为什么您可以在
jdbc()之后进一步链接?请暂停以下步骤:
启动服务器后,将此schema.sql放入SpringBoot将检测到的资源文件夹中。如果不使用SpringBoot,无需担心,只需从任何Mysql应用程序客户端(phpmyadmin、HeidiSQL、Navicat..)导入此脚本即可
如果存在oauth\u客户端详细信息,则删除表;
创建表oauth\u客户端\u详细信息(
客户端id VARCHAR(255)主键,
资源ID VARCHAR(255),
客户_secret VARCHAR(255),
范围VARCHAR(255),
授权授权类型VARCHAR(255),
web服务器重定向uri VARCHAR(255),
瓦查尔(255),
访问\u令牌\u有效性整数,
刷新\u令牌\u有效性整数,
附加信息VARCHAR(4096),
自动批准VARCHAR(255)
);
如果存在oauth_客户端_令牌,则删除表;
创建表oauth_客户端_令牌(
令牌id VARCHAR(255),
令牌长VARBINARY,
身份验证\u id VARCHAR(255)主键,
用户名VARCHAR(255),
客户id VARCHAR(255)
);
如果存在oauth\u访问\u令牌,则删除表;
创建表oauth\u访问\u令牌(
令牌id VARCHAR(255),
令牌长VARBINARY,
身份验证\u id VARCHAR(255)主键,
用户名VARCHAR(255),
客户id VARCHAR(255),
身份验证长VARBINARY,
刷新令牌VARCHAR(255)
);
如果存在oauth\u刷新\u令牌,则删除表;
创建表oauth\u刷新\u令牌(
令牌id VARCHAR(255),
令牌长VARBINARY,
身份验证长VARBINARY
);
如果存在oauth_代码,则删除表;
创建表oauth_代码(
代码VARCHAR(255),身份验证长VARBINARY
);
如果存在oauth_批准,则删除表格;
创建表oauth\u批准(
userId VARCHAR(255),
clientId VARCHAR(255),
范围VARCHAR(255),
状态VARCHAR(10),
到期时间戳,
lastModifiedAt时间戳
);
如果存在ClientDetails,则删除表;
创建表ClientDetails(
appId VARCHAR(255)主键,
resourceIds VARCHAR(255),
appSecret VARCHAR(255),
范围VARCHAR(255),
grantTypes VARCHAR(255),
重定向URL VARCHAR(255),
瓦查尔(255),
访问\u令牌\u有效性整数,
刷新\u令牌\u有效性整数,
附加信息VARCHAR(4096),
自动批准示波器VARCHAR(255)
);代码>
将数据源、authenticationManager、UserDetails服务注入到Othorization服务器中
@自动连线
私有MyUserDetails服务UserDetails服务;
@注入
私人AuthenticationManager AuthenticationManager;
@自动连线
私有数据源代码>
您将需要创建这两个bean
@Bean
公共JdbcTokenStore tokenStore(){
返回新的JdbcTokenStore(数据源);
}
@豆子
受保护的AuthorizationCodeServices AuthorizationCodeServices(){
返回新的JdbcAuthorizationCodeServices(数据源);
}
请不要忘记AuthorizationServer类顶部的@Configuration
配置要在mysql数据库中创建的客户端应用程序:clients.jdbc(dataSource).withClient(“clientapp”)
.authorizedGrantTypes(“密码”、“刷新令牌”)
.当局(“用户”)
.作用域(“读”、“写”)
.ResourceID(资源\u ID)
.机密(“123456”)代码>
你已经这么做了
最重要的事情(我想您已经忘记了…)是:要使用AuthorizationServerEndpointsConfigure配置您的端点:
endpoints.userDetailsService(userDetailsService).authorizationCodeServices(authorizationCodeServices()).authenticationManager(this.authenticationManager).tokenStore(tokenStore()).approvalStoreDisabled();
就这样,伙计,现在应该可以了;)
请随意要求更多。。。我很乐意帮忙
我已经从推特给你发了一条消息 @AndroidLover的答案很好,但可以简化。除非需要jdbc令牌存储,否则不需要创建oauth\u访问\u令牌、oauth\u刷新\u令牌等表
由于您只需要一个jdbc客户机详细信息服务,因此只需执行以下操作:
一,。创建客户端详细信息表oauth_client_details,例如:
drop table if exists oauth_client_details;
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)
);
二,。创建一个实现UserDetail接口的用户模型,例如(我使用的是SpringJPA,在本例中,您可以使用mybatis、jdbc等等):
四,。最后,配置您的身份验证服务器:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("dataSource")
DataSource dataSource;
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) {
configurer
.authenticationManager(authenticationManager)
.approvalStoreDisabled()
.userDetailsService(userDetailsService);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
{
clients
.jdbc(dataSource)
.inMemory().withClient("my-trusted-
client").secret("secret").accessTokenValiditySeconds(3600)
.scopes("read", "write").authorizedGrantTypes("password",
"refresh_token").resourceIds("resource");
}
}
这个问题已经很老了,但是没有一个回答回答了发问者原来的问题。我在熟悉spring的oauth2实现时遇到了同样的问题,我想知道为什么ClientDetailsServiceConfigurer
没有持久化通过JdbcClientDetailsServiceBuilder
以编程方式添加的客户机(通过调用jdbc(数据源)实例化)
方法),尽管网络上的所有教程都显示了类似的示例,如Wim发布的示例
@Service("userDetailsService")
public class UserService implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws
UsernameNotFoundException {
return userRepository.findByUsername(userName);
}
}
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("dataSource")
DataSource dataSource;
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) {
configurer
.authenticationManager(authenticationManager)
.approvalStoreDisabled()
.userDetailsService(userDetailsService);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
{
clients
.jdbc(dataSource)
.inMemory().withClient("my-trusted-
client").secret("secret").accessTokenValiditySeconds(3600)
.scopes("read", "write").authorizedGrantTypes("password",
"refresh_token").resourceIds("resource");
}
}
clients.jdbc(dataSource).withClient("clientapp")
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("123456").and().build();
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
if(!jdbcClientDetailsService.listClientDetails().isEmpty() ) {
jdbcClientDetailsService.removeClientDetails(CLIEN_ID);
}
if(jdbcClientDetailsService.listClientDetails().isEmpty() ) {
configurer.jdbc(dataSource).withClient(CLIEN_ID).secret(encoder.encode(CLIENT_SECRET))
.authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT)
.scopes(SCOPE_READ, SCOPE_WRITE, TRUST).accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS).and().build();
}
configurer.jdbc(dataSource).build().loadClientByClientId(CLIEN_ID);
}
if(!jdbcClientDetailsService.listClientDetails().isEmpty() ) {
jdbcClientDetailsService.removeClientDetails(CLIEN_ID);
}
if(jdbcClientDetailsService.listClientDetails().isEmpty() ) {
configurer.jdbc(dataSource).withClient(CLIEN_ID).secret(encoder.encode(CLIENT_SECRET))
.authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT)
.scopes(SCOPE_READ, SCOPE_WRITE, TRUST).accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS).and().build();
}
configurer.jdbc(dataSource).build().loadClientByClientId(CLIEN_ID);
@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
//...setting dataSource and databasePopulator
}
private DatabasePopulator databasePopulator() {
//...adding your schema script
}
@Bean
public DataSource dataSource() {
//...setting driverclassname, url, etc
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//...
clients.jdbc(this.dataSource()).withClient("example").(...).build()
}
create table IF NOT EXISTS 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 table IF NOT EXISTS oauth_client_token
(
token_id VARCHAR(256),
token bytea,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256)
);
create table IF NOT EXISTS oauth_access_token
(
token_id VARCHAR(256),
token bytea,
authentication_id VARCHAR(256) PRIMARY KEY,
user_name VARCHAR(256),
client_id VARCHAR(256),
authentication bytea,
refresh_token VARCHAR(256)
);
create table IF NOT EXISTS oauth_refresh_token
(
token_id VARCHAR(256),
token bytea,
authentication bytea
);
create table IF NOT EXISTS oauth_code
(
code VARCHAR(256),
authentication bytea
);
create table IF NOT EXISTS oauth_approvals
(
userId VARCHAR(256),
clientId VARCHAR(256),
scope VARCHAR(256),
status VARCHAR(10),
expiresAt TIMESTAMP,
lastModifiedAt TIMESTAMP
);
-- customized oauth_client_details table
create table IF NOT EXISTS 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)
);
@Configuration
@EnableAuthorizationServer
class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
@Qualifier("dataSource")
DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer authorizationServerEndpointsConfigurer) throws Exception {
authorizationServerEndpointsConfigurer.tokenStore(tokenStore());
}
}