一、ReactiveRedisTemplate使用fastjson进行序列化配置
- 首先在maven中引入reactive redis包和fastjson包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
- 编写RedisAutoConfig.class进行自定义ReactiveRedisTemplate Bean配置
我这里使用的是ReactiveRedisTemplate<String, Object>,key为String类型,value为Object类型,这样value可以直接使用Java对象操作,不需要显示进行fastjson的序列化和反序列化。
需要注意的是new ReactiveRedisTemplate时需要传入1个RedisSerializationContext对象,redis的key、value序列化方式就配置在RedisSerializationContext中。
这里我们使用StringRedisSerializer进行key和hashKey的序列化,使用fastjson的GenericFastJsonRedisSerializer进行value和hashValue的序列化。
@Configuration
public class RedisAutoConfig {
@Bean
public ReactiveRedisTemplate<String, Object> reactiveRedisTemplate(LettuceConnectionFactory connectionFactory) {
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
RedisSerializationContext.SerializationPair<String> keySerializationPair =
RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer);
RedisSerializationContext.SerializationPair<Object> valueSerializationPair =
RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
RedisSerializationContext.SerializationPair<Object> hashValueSerializationPair =
RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
RedisSerializationContext<String, Object> context = new RedisSerializationContext<String, Object>() {
@Override
public SerializationPair getKeySerializationPair() {
return keySerializationPair;
}
@Override
public SerializationPair getValueSerializationPair() {
return valueSerializationPair;
}
@Override
public SerializationPair getHashKeySerializationPair() {
return keySerializationPair;
}
@Override
public SerializationPair getHashValueSerializationPair() {
return hashValueSerializationPair;
}
@Override
public SerializationPair<String> getStringSerializationPair() {
return keySerializationPair;
}
};
return new ReactiveRedisTemplate<>(connectionFactory, context);
}
}
这样配置完成后,就可以直接自动注入ReactiveRedisTemplate<String, Object>对象
@Autowired
private ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;
二、在SpringCloudGateway中使用ReactiveRedisTemplate进行自定义token校验
- 首先在maven中引入spring cloud gateway依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 编写自定义filter factory TokenVerifyGatewayFilterFactory进行自定义token校验
首先从request的header中取出token字段,根据token查询redis,取出token对应的用户id,如果用户id存在则token有效,如果不存在则返回token无效。
@Component
public class TokenVerifyGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Autowired
private ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String token = request.getHeaders().get("token").get(0);
return this.getUserId(token).flatMap(op -> {
//1、判断redis中是否存在对应缓存,不存在则直接返回token无效
if (!op.isPresent()) {
ServerHttpResponse response = exchange.getResponse();
byte[] bits = "token无效".getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
//2、缓存有效,获取userId,进行日志记录或者其他操作
System.out.println("redis缓存token用户:" + op.get());
//3、token鉴权通过,继续执行filter完成转发
return chain.filter(exchange);
});
};
}
private Mono<Optional<String>> getUserId(String token) {
//a、以reactive的方式查询redis,获取token对应value值
return this.reactiveRedisTemplate.opsForValue().get(token)
//b、对redis返回结果进行Optional封装,这里v为String类型的用户id
.map(v -> Optional.ofNullable((String)v))
//c、如果token无效,b不会执行,在这里返回1个值为null的Optional对象
.switchIfEmpty(Mono.just(Optional.ofNullable(null)));
}
}
三、测试
- 编写SpringCloudGateway配置文件
对于任意uri,都使用TokenVerifyGatewayFilterFactory进行请求过滤,并将localhost:8080的任意请求转发至https://www.baidu.com。
spring:
cloud:
gateway:
routes:
- id: testRoute
uri: https://www.baidu.com
predicates:
- Path=/**
filters:
- TokenVerify
- Redis缓存数据设置
在Redis中缓存key="goodToken",value="magicTan",即goodToken是合法token,用户id为magicTan。如果使用不合法token如invalidToken就无法取到用户id。
- 运行项目进行测试
调用localhost:8080,header中设置token为goodToken,可以看到请求转发至百度,并且控制台输出了缓存的用户id magicTan:
调用localhost:8080,header中设置token为invalidToken,可以看到返回结果为“token无效”:
项目地址:码云
欢迎扫码关注我微信公众号:magicTan。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。