一、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的序列化。
@Configurationpublic 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>对象
@Autowiredprivate 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有效。
@Componentpublic 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。