Redis替换Jdbc
添加redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
设置RedisTokenStore进行token存储
private final RedisConnectionFactory factory;
@Bean
public TokenStore tokenStore() {
return new RedisTokenStore(factory);
}
使用redis替换JdbcAuthorizationCodeServices
仿照JdbcAuthorizationCodeServices,实现一个自定义SpringRedisAuthorizationCodeServices类来存储授权码
public class SpringRedisAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {
private final RedisTemplate<String, OAuth2Authentication> redisTemplate;
public SpringRedisAuthorizationCodeServices(RedisTemplate<String, OAuth2Authentication> redisTemplate) {
Assert.notNull(redisTemplate, "RedisTemplate required");
this.redisTemplate = redisTemplate;
}
@Override
protected void store(String code, OAuth2Authentication authentication) {
redisTemplate.opsForValue().set("oauth2:oauth_code:" + code, authentication, 10, TimeUnit.MINUTES);
}
@Override
protected OAuth2Authentication remove(String code) {
OAuth2Authentication token = redisTemplate.opsForValue().get("oauth2:oauth_code:" + code);
this.redisTemplate.delete("oauth2:oauth_code:" + code);
return token;
}
}
设置SpringRedisAuthorizationCodeServices
private final RedisTemplate<String, Object> redisTemplate;
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new SpringRedisAuthorizationCodeServices(redisTemplate);
}
配置redis
创建RedisConfig配置类,注意只能采用JdkSerializationRedisSerializer进行字符串的序列化,不然读取授权码的时候会报错。
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Resource
private RedisConnectionFactory factory;
@Override
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".").append(method.getName());
if (params.length > 0) {
sb.append(".");
}
for (Object param : params) {
sb.append(param.toString());
}
return sb.toString();
};
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
return redisTemplate;
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver(Objects.requireNonNull(cacheManager()));
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 用于捕获从Cache中进行CRUD时的异常的回调处理器。
return new SimpleCacheErrorHandler();
}
@Bean
@Override
public CacheManager cacheManager() {
RedisCacheConfiguration cacheConfiguration =
defaultCacheConfig()
.disableCachingNullValues()
// 默认缓存过期时间8天+随机秒数,防止集中过期
.entryTtl(Duration.ofDays(8).plusSeconds(new Random().nextInt(100)))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
}
}
设置redis key前缀
@Bean
public TokenStore tokenStore() {
RedisTokenStore tokenStore = new RedisTokenStore(factory);
tokenStore.setPrefix("oauth2:");
return tokenStore;
}
测试
密码模式
获取token
POST http://localhost:8090/oauth/token
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic b3JkZXI6c2VjcmV0
grant_type=password&username=user&password=password
响应:
{
"access_token": "756a8b37-f14d-4402-9969-f72d261e34b2",
"token_type": "bearer",
"refresh_token": "45d12dbb-4c9c-4cef-b711-c0cbbd3d15c7",
"expires_in": 2591999,
"scope": "read write"
}
请求受保护资源
GET http://localhost:8092/api/order
Authorization: Bearer 756a8b37-f14d-4402-9969-f72d261e34b2
响应:
userId:1406151407442780160,phone:,openId:
Response code: 200; Time: 41ms; Content length: 41 bytes
授权码模式
GET http://localhost:8090/oauth/authorize?client_id=order&response_type=code&grant_type=authorization_code&redirect_uri=http://www.baidu.com
响应:
https://www.baidu.com/?code=CXmj01
继续获取token
POST http://localhost:8090/oauth/token
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic b3JkZXI6c2VjcmV0
grant_type=authorization_code&client_id=order&client_secret=secret&redirect_uri=http://www.baidu.com&code=CXmj01
响应:
{
"access_token": "ea2d2e3b-4dd9-4fa5-bbb7-0ceb56d3fb0a",
"token_type": "bearer",
"refresh_token": "36abfc53-2f24-4f2e-8efe-5a32da8e5da2",
"expires_in": 2591786,
"scope": "read write"
}
查看redis,相关token信息已经存储在里面了