Redis存储令牌:分布式之便
前言
我们都是把令牌存储在内存中的,这样如果部署多个服务,就会导致无法使用令牌的问题。 Spring Cloud Security中有两种存储令牌的方式可用于解决该问题,一种是使用Redis来存储,另一种是使用JWT来存储。JWT存储在客户端,验证的时候,会带上这个内容。但是因为存储在浏览器端,在服务端共享则不是很方便,我们将token存在Redis中,这样分布式缓存就能共享这个token了。这对于分布式系统而言,还是很有优势的。
一、存储方式对比
我们还是来回顾一下JWT的流程:
JWT方式最大的坏处就是无法主动让token失效,小伙伴们会说token不是有过期时间吗?是的,token本身是有过期时间,但token一旦发出,服务器就无法收回。
还有个问题就是因为jwt中包含了用户的部分信息,如果这些部分信息修改了,服务器获取的还是以前的jwt中的用户信息,导致数据不一致。
这两种缺点,虽然因为JWT存储在客户端,能够减少存储压力,但是缺陷也很明显。那我们还是使用传统的Sesion-Cookie服务器,似乎更好。
但是我们后来用到了分布式缓存Redis,这比传统的Sesion-Cookie服务器更有优势。
我们分析一下Redis存储Token的流程:
1.前端服务器收到用户登录请求,传给后台API网关。
2.API网关把请求分发到用户服务里进行身份验证。
3.后台用户服务验证通过,然后从账号信息抽取出userName、login_time等基本信息组成payload,进而组装一个JWT,把JWT放入redis,然后包装cookie中返回到前端服务器,这就登录成功了。
4.前端服务器拿到JWT,进行存储,登录后,再访问其他微服务的时候,前端会携带jwt访问后台,后台校验 JWT,验证通过后,返回相应资源和数据就可以了。
二、Redis存储token
1.添加依赖和配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis: #redis相关配置
password: 123456 #有密码时设置
2 .添加在Redis中存储令牌的配置
@Configuration
public class RedisTokenStoreConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore (){
return new RedisTokenStore(redisConnectionFactory);
}
}
3 .在认证服务器配置中指定令牌的存储策略为Redis
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserService userService;
@Autowired
@Qualifier("redisTokenStore")
private TokenStore tokenStore;
/**
* 使用密码模式需要配置
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userService)
.tokenStore(tokenStore);//配置令牌存储策略
}
//省略代码...
}
运行项目后使用密码模式来获取令牌,访问如下地址:http://localhost:9401/oauth/token
进行获取令牌操作,可以发现令牌已经被存储到Redis中
总结
如果项目并不大,JWT是个好选择,但是一旦下发便不受服务端控制,如果发生token泄露,服务器也只能任其蹂躏,在其未过期期间不能有任何措施对此模式践行比较完善的框架推荐你了解一下token+redis,此框架扩展了token-session模型,将会话数据放在了Redis下,并提供了多种Session序列化方案,诸如注销登录、权限认证、踢人下线等常见功能全部一行代码就可以完成,这是一种类似于分布式session的解决方案,非常适合分布式系统。