OAuth + Security

PS:此文章为系列文章,建议从第一篇开始阅读。

在之前的所有配置中,我们的客户端信息和授权码模式下的授权码任然还是存储在数据库中的,这样就不利于我们后期的扩展,所以在正式的生成环境中,我们一般将其存储在数据库中。

建表

首先,根据OAuth官方给的数据库建表实例创建相应的表,这里我们只需要oauth_client_details和oauth_code

############################## oauth_client_details #############################
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details`(
`client_id` varchar(255)  CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端标
识',
`resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '接入资源列表',
`client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户端秘钥',
`scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`access_token_validity` int(11) NULL DEFAULT NULL,
`refresh_token_validity` int(11) NULL DEFAULT NULL,
`additional_information` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0),
`archived` tinyint(4) NULL DEFAULT NULL,
`trusted` tinyint(4) NULL DEFAULT NULL,
`autoapprove` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`client_id`) USING BTREE
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '接入客户端信息'
ROW_FORMAT = Dynamic;

INSERT INTO `oauth_client_details` VALUES ('dimples', 'res1',
'$2a$10$NlBC84MVb7F95EXYTXwLneXgCca6/GipyWR5NHm8K0203bSQMLpvm', 'all',
'client_credentials,password,authorization_code,implicit,refresh_token','http://www.baidu.com',
NULL,7200,259200,NULL,'2020-06-02 16:04:28',0,0,'false');

############################## oauth_code #################################
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code`(
`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`authentication` blob NULL,
INDEX `code_index`(`code`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

此处的client_secret是加密过后的秘钥

image

注意:官方给的标准SQL建表语句的数据库是HSQL,实际使用需要根据数据库类型自己修改

修改认证服务器

  1. 修改客户端配置
@Resource
private DataSource dataSource;

// 新增
@Bean
public ClientDetailsService clientDetailsService(DataSource dataSource) {
    ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
    ((JdbcClientDetailsService) clientDetailsService).setPasswordEncoder(passwordEncoder());
    return clientDetailsService;
}

// 修改
@Override
public void configure(ClientDetailsServiceConfigurer clients)throws Exception{
    clients.withClientDetails(clientDetailsService); 
}

同时需要添加jdbc的依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
  1. 修改授权码存储配置
// 修改
@Bean
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) { 
    //设置授权码模式的授权码如何存取
    return new JdbcAuthorizationCodeServices(dataSource);
}

扩展

我们点开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格式不支持,我们将无法获取Token,那么我们怎么解决呢?官方也提供了方法:

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
    jdbcClientDetailsService.setFindClientDetailsSql("");
    clients.withClientDetails(jdbcClientDetailsService);
}

在配置客户端信息的时候我们可以自定义SQL语句去替换默认的。

原文地址:https://www.cnblogs.com/reroyalup/p/13032284.html