Spring Security TokenStore实现3+1详解

TokenStore:Persistence interface for OAuth2 tokens.(对于OAuth2令牌持久化接口)
官方文档
TokenStore 的默认实现有三种:html

  • InMemoryTokenStore
  • JdbcTokenStore
  • JwtTokenStore

spring 关于tokenstore的文档

此外,将会根据TokenStor的特性多自定义一种实现——RedisTokenStorejava

1、InMemoryTokenStore

1.1.概要

这个是OAuth2默认采用的实现方式。在单服务上能够体现出很好特效(即并发量不大,而且它在失败的时候不会进行备份),大多项目均可以采用此方法。根据名字就知道了,是存储在内存中,毕竟存在内存,而不是磁盘中,调试简易。mysql

1.2.实现

既然InMemoryTokenStore是OAuth2默认实现,那么就不须要咱们再去配置,直接调用便可。 redis

InMemoryTokenStore 实现

1.3.代码调用

@Autowired(required = false)
private TokenStore inMemoryTokenStore;
/** * 端点(处理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
   endpoints.tokenStore(inMemoryTokenStore);
   ....
}
复制代码

1.4.测试调用访问获取Token

此处基于SpringBoot+Security的小demo,相关配置就不在本文太多出现,着重讲解TokenStorespring

  • spring security 默认受权认证端点:oauth/token
  • 此处使用:grant_type—>password模式

InMemoryTokenStore 测试

2、JdbcTokenStore

2.1.概要

这个是基于JDBC的实现,令牌(Access Token)会保存到数据库。这个方式,能够在多个服务之间实现令牌共享。sql

2.2.实现

1).既然是JDBC,那么确定得须要一个数据源。此处使用的是SpringBoot,所以配置了一个数据源。所需jar依赖就很少说了。数据库

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?useUnicode=yes&characterEncoding=UTF-8
    username: catalpaFlat
    password: catalpaFlat
复制代码

2).除了数据源,那么jdbc确定得有库表,所以OAuth2默认给出了表结构api

Drop table  if exists oauth_access_token;
create table oauth_access_token (
  create_time timestamp default now(),
  token_id VARCHAR(255),
  token BLOB,
  authentication_id VARCHAR(255),
  user_name VARCHAR(255),
  client_id VARCHAR(255),
  authentication BLOB,
  refresh_token VARCHAR(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Drop table  if exists oauth_refresh_token;
create table oauth_refresh_token (
  create_time timestamp default now(),
  token_id VARCHAR(255),
  token BLOB,
  authentication BLOB
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
复制代码

并且JdbcTokenStore源码中也有不少关于表的操做: 安全

JdbcTokenStore 源码

3).配置JdbcTokenStore并发

@Autowired
private DataSource dataSource;
/** * jdbc token 配置 */
@Bean
public TokenStore jdbcTokenStore() {
    Assert.state(dataSource != null, "DataSource must be provided");
    return new JdbcTokenStore(dataSource);
}
复制代码

2.3.代码调用

@Autowired(required = false)
private TokenStore jdbcTokenStore;
/** * 端点(处理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
   endpoints.tokenStore(jdbcTokenStore);
   ....
}
复制代码

2.4.测试调用访问获取Token

JdbcTokenStore 测试
JdbcTokenStore 测试
JdbcTokenStore 测试
JdbcTokenStore 测试

3、JwtTokenStore

3.1.概要

jwt全称 JSON Web Token。这个实现方式不用管如何进行存储(内存或磁盘),由于它能够把相关信息数据编码存放在令牌里。JwtTokenStore 不会保存任何数据,可是它在转换令牌值以及受权信息方面与 DefaultTokenServices 所扮演的角色是同样的。

3.2.实现

既然jwt是将信息存放在令牌中,那么就得考虑其安全性,所以,OAuth2提供了JwtAccessTokenConverter实现,添加jwtSigningKey,以今生成秘钥,以此进行签名,只有jwtSigningKey才能获取信息。

/** * jwt Token 配置, matchIfMissing = true * * @author : CatalpaFlat */
@Configuration
public class JwtTokenConfig {

   private final Logger logger = LoggerFactory.getLogger(JwtTokenConfig.class);
   @Value("${default.jwt.signing.key}")
   private String defaultJwtSigningKey;
   @Autowired
   private CustomYmlConfig customYmlConfig;

   public JwtTokenConfig() {logger.info("Loading JwtTokenConfig ...");}

   @Bean
   public TokenStore jwtTokenStore() {
       return new JwtTokenStore(jwtAccessTokenConverter());
   }

   @Bean
   public JwtAccessTokenConverter jwtAccessTokenConverter() {
       JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
       String jwtSigningKey = customYmlConfig.getSecurity().getOauth2s().getOuter().getJwtSigningKey();
       Assert.state(StringUtils.isBlank(jwtSigningKey), "jwtSigningKey is not configured");
       //秘签
       jwtAccessTokenConverter.setSigningKey(StringUtils.isBlank(jwtSigningKey) ? defaultJwtSigningKey : jwtSigningKey);
       return jwtAccessTokenConverter;
   }
}
复制代码

3.3.代码调用

@Autowired(required = false)
private TokenStore jwtTokenStore;
@Autowired(required = false)
private JwtAccessTokenConverter jwtAccessTokenConverter;
/** * 端点(处理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
   endpoints.tokenStore(jwtTokenStore)
   .accessTokenConverter(jwtAccessTokenConverter);
   ....
}
复制代码

3.4.测试调用访问获取Token

JwtTokenStore 测试
JwtTokenStore 测试

4、RedisTokenStore

4.1.概要

因为TokenStore做用就是对于OAuth2令牌持久化接口,而咱们在实际开发中,对于内存的使用是慎之又慎,而对于存储到数据库也是根据项目需求进行调配。所以就想,可不能够用redis来进行存储持久化咱们的OAuth2令牌。偷偷瞄了一眼OAuth2还有那些实现了TokenStore的,找到了一个RedisTokenStore。

RedisTokenStore 概述

4.2.实现

记得配置redis

@Autowired
private RedisConnectionFactory redisConnectionFactory;
/** * redis token 配置 */
@Bean
public TokenStore redisTokenStore() {
    return new RedisTokenStore(redisConnectionFactory);
}
复制代码

4.3.代码调用

@Autowired(required = false)
private TokenStore redisTokenStore;
/** * 端点(处理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
   endpoints.tokenStore(redisTokenStore);
   ....
}
复制代码

4.4.测试调用访问获取Token

RedisTokenStore 测试
RedisTokenStore 测试
相关文章
相关标签/搜索