ReactiveRedisTemplate uses FastJSON for serialization configuration

  1. The Reactive Redis package and the FastJSON package are first introduced in Maven
<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>
Copy the code
  1. Write redisAutoconfig. class to customize the ReactiveRedisTemplate Bean configuration

Here I use ReactiveRedisTemplate<String, Object> with key as String and value as Object, so that value can be manipulated directly with Java objects without the need to display fastjson serialization and deserialization.

It is important to note the new 1 RedisSerializationContext ReactiveRedisTemplate require incoming object, redis key and the value of configuration in RedisSerializationContext serialized way.

Here we use StringRedisSerializer key and hashKey serialization, use value and hashValue fastjson GenericFastJsonRedisSerializer for serialization.

@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(a) {
                return keySerializationPair;
            }

            @Override
            public SerializationPair getValueSerializationPair(a) {
                return valueSerializationPair;
            }

            @Override
            public SerializationPair getHashKeySerializationPair(a) {
                return keySerializationPair;
            }

            @Override
            public SerializationPair getHashValueSerializationPair(a) {
                return hashValueSerializationPair;
            }

            @Override
            public SerializationPair<String> getStringSerializationPair(a) {
                returnkeySerializationPair; }};return newReactiveRedisTemplate<>(connectionFactory, context); }}Copy the code

After this configuration is complete, the ReactiveRedisTemplate<String, Object> Object can be injected directly and automatically

@Autowired
private ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;
Copy the code

2. Customize token verification using ReactiveRedisTemplate in SpringCloudGateway

  1. Start by introducing the Spring Cloud Gateway dependency in Maven
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Copy the code
  1. Writing a custom filter factory TokenVerifyGatewayFilterFactory customize token validation

First, retrieve the token field from the header of the request, query redis based on the token, and retrieve the user ID corresponding to the token. If the user ID exists, the token is valid; if not, the token is invalid.

@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 -> {
                Check whether there is a corresponding cache in redis. If there is no cache, the token returned is invalid
                if(! op.isPresent()) { ServerHttpResponse response = exchange.getResponse();byte[] bits = "The token is invalid".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. The cache is valid. Obtain the userId and perform other operations
                System.out.println(Redis cache token user: + op.get());
                //3. If the token authentication succeeds, run the filter command to complete the forwarding
                return chain.filter(exchange);
            });
        };
    }

    private Mono<Optional<String>> getUserId(String token) {
        //a. Query redis in reactive mode to obtain the value of the token
        return this.reactiveRedisTemplate.opsForValue().get(token)
                // select * from redis where v is the user ID of type String
                .map(v -> Optional.ofNullable((String)v))
                // if the token is invalid, b will not execute it
                .switchIfEmpty(Mono.just(Optional.ofNullable(null))); }}Copy the code

Three, test,

  1. Write the SpringCloudGateway configuration file

For any uri, using TokenVerifyGatewayFilterFactory request filtering, and will be localhost: 8080 forward any request to www.baidu.com.

spring:
  cloud:
    gateway:
      routes:
        - id: testRoute
          uri: https://www.baidu.com
          predicates:
            - Path=/**
          filters:
            - TokenVerify
Copy the code
  1. Redis cache data Settings

Cache key=”goodToken” and value=”magicTan” in Redis. That is, The goodToken is a valid token and the user ID is magicTan. If an invalidToken such as an invalidToken is used, the user id cannot be obtained.

  1. Run the project for testing

Call localhost:8080, set token to goodToken in header, you can see that the request is forwarded to Baidu, and the console outputs the cached user ID magicTan:

Localhost :8080, header = invalidToken, token is invalid

Project Address: Code Cloud


Please scan the code to follow my wechat official account: magicTan.