Spring Security Oauth2:RedisTokenStore(二)之JSON序列化

RedisTokenStore:Json序列化

一. 前言

Spring Security Oauth2 存储Token的方式有多种, 比如JWT、Jdbc(数据库)、Redis等,但是对于一个大型的分布式服务应用,Redis存储方式应该是最佳选择。

二. 问题

我们使用默认的Redis存储方式,序列化到到Redis的数据是采用JDK序列化策略写入到redis的。这样对于程序的功能毫无影响,但是对于开发者却很不直观,出现问题,也不容易排查,我们能不能把它们序列化成JSON格式呢?image.png

默认序列化方式

Spring Security Oauth2 Redis序列化Token相关的数据是采用JdkSerializationStrategy,用这个序列化策略序列化出的结果正如上图所示那样,具体的代码如下:

//org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore

public class RedisTokenStore implements TokenStore {
   

	private static final String ACCESS = "access:";
	private static final String AUTH_TO_ACCESS = "auth_to_access:";
	private static final String AUTH = "auth:";
	private static final String REFRESH_AUTH = "refresh_auth:";
	private static final String ACCESS_TO_REFRESH = "access_to_refresh:";
	private static final String REFRESH = "refresh:";
	private static final String REFRESH_TO_ACCESS = "refresh_to_access:";
	private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:";
	private static final String UNAME_TO_ACCESS = "uname_to_access:";

	private static final boolean springDataRedis_2_0 = ClassUtils.isPresent(
			"org.springframework.data.redis.connection.RedisStandaloneConfiguration",
			RedisTokenStore.class.getClassLoader());

	private final RedisConnectionFactory connectionFactory;
	private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator();
	//Jdk序列方式
    private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
    ......省略无关代码

Fastjson序列化策略

笔者首先想到的是自定义一个RedisTokenStoreSerializationStrategy**,**接口的实现改成Object和JSONString之间的序列化、反序列应该就好了,于是笔者使用Fastjson实现了一个序列化策略,并注入到Spring Bean容器中,如下:

public class FastjsonRedisTokenStoreSerializationStrategy implements RedisTokenStoreSerializationStrategy {
   

    private final static ParserConfig defaultRedisConfig = new ParserConfig();

    static {
   
        defaultRedisConfig.setAutoTypeSupport(true);
    }

    static {
   
        //设置Fastjson Json自动转换为Java对象
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    @Override
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
   
        Preconditions.checkArgument(clazz != null,
            "clazz can't be null");
        if (bytes == null || bytes.length == 0) {
   
            return null;
        }

        try {
   
            return JSON.parseObject(new String(bytes, IOUtils.UTF8), clazz, defaultRedisConfig);
        } catch (Exception ex) {
   
            throw new SerializationException("Could not serialize: " + ex.getMessage(), ex);
        }
    }

    @Override
    public String deserializeString(byte[] bytes) {
   
        if (bytes == null || bytes.length == 0) {
   
            return null;
        }
        return new String(bytes, IOUtils.UTF8);
    }

    @Override
    public byte[] serialize(Object object) {
   
        if (object == null) {
   
            return new byte[0];
        }

        try {
   
            return JSON.toJSONBytes(object, SerializerFeature.WriteClassName,
                SerializerFeature.DisableCircularReferenceDetect);
        } catch (Exception ex) {
   
            throw new SerializationException("Could not serialize: " + ex.getMessage(), ex);
        }
    }

    @Override
    public byte[] serialize(String data) {
   
        if (data == null || data.length() == 0) {
   
            return new byte[0];
        }

        return data.getBytes(Charset.forName("utf-8"));
    }
}
@Bean
public RedisTokenStore redisTokenStore(){
   
    RedisTokenStore store = new RedisTokenStore(redisConnectionFactory);
    store.setSerializationStrategy(new FastjsonRedisTokenStoreSerializationStrategy());
    return store;
}

笔者刚开始以为这样处理就可以了,OAuth2Authentication 这个类并没有默认构造方法,会导致Fastjson反序列化失败,因此针对Oauth2等无法序列化或者反序列化的类需要特殊化处理。针对DefaultOAuth2RefreshToken、OAuth2Authentication等特殊的类,我们需要定制化序列化以及反序列化策略。下面是笔者项目的配置以及序列化和反序列策略,有些类是满足需求定制的,不在Spring Security包中。提供只是参考思路,不可照抄。配置和自定义策略如下:

public class FastjsonRedisTokenStoreSerializationStrategy implements RedisTokenStoreSerializationStrategy {
   

    private static ParserConfig config = new ParserConfig(<
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值