15.7 客户端信息存入数据库
在 15.5.2.1 小节搭建的授权服务器中,客户端信息是直接存储在内存中的。然而在实际项目中,这种方式并不可取,一方面客户端信息无法实现动态添加与删除,另一方面硬编码的客户端信息也不好维护,所以我们需要将客户端信息存入数据库中。
涉及客户端信息保存的接口主要是 ClientDetailsService,这个接口主要有两个实现类,如图 15-18 所示。
图 15-18 ClientDetailsService 的实现类
InMemoryClientDetailsService 就是将客户端信息存入内存中,也就是我们之前案例所采用的存储方式;JdbcClientDetailsService 则是将客户端信息存入数据库中。
由于官方没有给出使用 JdbcClientDetailsService 存储客户端信息时的数据库脚本,所以我们可以根据 JdbcClientDetailsService 中定义的 SQL 来分析出数据库表结构。JdbcClientDetailsService 部分源码:
private static final String CLIENT_FIELDS_FOR_UPDATE = "resource_ids, scope, " + "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "+"refresh_token_validity, additional_information, autoapprove"; private static final String CLIENT_FIELDS = "client_secret, " + CLIENT_FIELDS_FOR_UPDATE;
根据这两个属性就能确定数据库字段名,最终分析出来的 SQL 如下:
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;
在数据库中执行该段 SQL 脚本,并将一开始配置在代码中的客户端信息录入数据库中,如图 15-19 所示。
图 15-19 客户端信息
然后在授权服务器 auth-server 中添加如下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
在 application.properties 中配置一下数据库连接信息:
spring.datasource.url=jdbc:mysql:///security15?useUnicode=true&characterEncod ing=UTF-8&serverTimezone=Asia/Shanghai spring.datasource.password=123 spring.datasource.username=root spring.main.allow-bean-definition-overriding=true
最后一条配置是允许 Bean 的覆盖,否则我们自己创建的 ClientDetailsService 将会和系统创建的 ClientDetailsService 实例相冲突。
接下来配置 ClientDetailsService 实例,代码如下:
@EnableAuthorizationServer @Configuration public class AuthorizationServer extends AuthorizationServerConfigurerAdapter { @Autowired DataSource dataSource; @Bean ClientDetailsService clientDetailsService() { return new JdbcClientDetailsService(dataSource); } @Bean AuthorizationServerTokenServices tokenServices() { DefaultTokenServices services = new DefaultTokenServices(); services.setClientDetailsService(clientDetailsService()); services.setSupportRefreshToken(true); services.setTokenStore(tokenStore); return services; } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService()); } //省略其他 }
和 15.5.2.1 小节中的案例相比,这里的变化主要在四个方面:
(1)注入 DataSource 实例。
(2)向 Spring 容器注册一个 JdbcClientDetailsService 实例。
(3)在 AuthorizationServerTokenServices 实例中除去令牌有效期设置,令牌有效期将从数据库中加载。
(4)在 configure(ClientDetailsServiceConfigurer) 方法中直接配置 JdbcClientDetailsService 实例即可,项目启动后会自动从数据库中加载客户端信息。
配置完成后,重启授权服务器再去进行授权测试即可。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论