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 測試
相關文章
相關標籤/搜索