TokenStore:Persistence interface for OAuth2 tokens.(對於OAuth2令牌持久化接口)
官方文檔
TokenStore 的默認實現有三種:html
- InMemoryTokenStore
- JdbcTokenStore
- JwtTokenStore
此外,將會根據TokenStor的特性多自定義一種實現——RedisTokenStorejava
這個是OAuth2默認採用的實現方式。在單服務上能夠體現出很好特效(即併發量不大,而且它在失敗的時候不會進行備份),大多項目均可以採用此方法。根據名字就知道了,是存儲在內存中,畢竟存在內存,而不是磁盤中,調試簡易。mysql
既然InMemoryTokenStore是OAuth2默認實現,那麼就不須要咱們再去配置,直接調用便可。 redis
@Autowired(required = false)
private TokenStore inMemoryTokenStore;
/** * 端點(處理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(inMemoryTokenStore);
....
}
複製代碼
此處基於SpringBoot+Security的小demo,相關配置就不在本文太多出現,着重講解TokenStorespring
這個是基於JDBC的實現,令牌(Access Token)會保存到數據庫。這個方式,能夠在多個服務之間實現令牌共享。sql
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源碼中也有不少關於表的操做: 安全
3).配置JdbcTokenStore併發
@Autowired
private DataSource dataSource;
/** * jdbc token 配置 */
@Bean
public TokenStore jdbcTokenStore() {
Assert.state(dataSource != null, "DataSource must be provided");
return new JdbcTokenStore(dataSource);
}
複製代碼
@Autowired(required = false)
private TokenStore jdbcTokenStore;
/** * 端點(處理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(jdbcTokenStore);
....
}
複製代碼
jwt全稱 JSON Web Token。這個實現方式不用管如何進行存儲(內存或磁盤),由於它能夠把相關信息數據編碼存放在令牌裏。JwtTokenStore 不會保存任何數據,可是它在轉換令牌值以及受權信息方面與 DefaultTokenServices 所扮演的角色是同樣的。
既然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;
}
}
複製代碼
@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);
....
}
複製代碼
因爲TokenStore做用就是對於OAuth2令牌持久化接口,而咱們在實際開發中,對於內存的使用是慎之又慎,而對於存儲到數據庫也是根據項目需求進行調配。所以就想,可不能夠用redis來進行存儲持久化咱們的OAuth2令牌。偷偷瞄了一眼OAuth2還有那些實現了TokenStore的,找到了一個RedisTokenStore。
記得配置redis
@Autowired
private RedisConnectionFactory redisConnectionFactory;
/** * redis token 配置 */
@Bean
public TokenStore redisTokenStore() {
return new RedisTokenStore(redisConnectionFactory);
}
複製代碼
@Autowired(required = false)
private TokenStore redisTokenStore;
/** * 端點(處理入口) */
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(redisTokenStore);
....
}
複製代碼