由于项目需要, 需要将原项目中间件国产化, 其中Redis需要国产化为TongRDS;整个配置过程很简单, 就是集成oauth2的时候出了序列化问题, 提供商已经修改了这个bug, 所以不能完整提供数据; 在提供商没有修改这个bug之前,需要更改默认的序列化方式;
@Configuration
public class MyTokenStoreConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore tokenStore() {
RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
redisTokenStore.setSerializationStrategy(new FastjsonRedisTokenStoreSerializationStrategy());
return redisTokenStore;
}
}
复制代码
public class FastjsonRedisTokenStoreSerializationStrategy implements RedisTokenStoreSerializationStrategy {
private static ParserConfig config = new ParserConfig();
static {
init();
}
protected static void init() {
//自定义oauth2序列化:DefaultOAuth2RefreshToken 没有setValue方法,会导致JSON序列化为null
config.setAutoTypeSupport(true);//开启AutoType
//自定义DefaultOauth2RefreshTokenSerializer反序列化
config.putDeserializer(DefaultOAuth2RefreshToken.class, new DefaultOauth2RefreshTokenSerializer());
//自定义OAuth2Authentication反序列化
config.putDeserializer(OAuth2Authentication.class, new OAuth2AuthenticationSerializer());
//添加autotype白名单
config.addAccept("org.springframework.security.oauth2.provider.");
config.addAccept("org.springframework.security.oauth2.provider.client");
TypeUtils.addMapping("org.springframework.security.oauth2.provider.OAuth2Authentication",
OAuth2Authentication.class);
TypeUtils.addMapping("org.springframework.security.oauth2.provider.client.BaseClientDetails",
BaseClientDetails.class);
config.addAccept("org.springframework.security.oauth2.common.");
TypeUtils.addMapping("org.springframework.security.oauth2.common.DefaultOAuth2AccessToken", DefaultOAuth2AccessToken.class);
TypeUtils.addMapping("org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken", DefaultExpiringOAuth2RefreshToken.class);
config.addAccept("org.springframework.security.web.authentication.preauth");
TypeUtils.addMapping("org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken", PreAuthenticatedAuthenticationToken.class);
}
@Override
public <T> T deserialize(byte[] bytes, Class<T> aClass) {
Preconditions.checkArgument(aClass != null,
"clazz can't be null");
if (bytes == null || bytes.length == 0) {
return null;
}
try {
return JSON.parseObject(new String(bytes, IOUtils.UTF8), aClass, config);
} 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 o) {
if (o == null) {
return new byte[0];
}
try {
return JSON.toJSONBytes(o, 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"));
}
}
复制代码
public class DefaultOauth2RefreshTokenSerializer implements ObjectDeserializer {
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type == DefaultOAuth2RefreshToken.class) {
JSONObject jsonObject = parser.parseObject();
String tokenId = jsonObject.getString("value");
DefaultOAuth2RefreshToken refreshToken = new DefaultOAuth2RefreshToken(tokenId);
return (T) refreshToken;
}
return null;
}
@Override
public int getFastMatchToken() {
return 0;
}
}
复制代码
public class OAuth2AuthenticationSerializer implements ObjectDeserializer {
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type == OAuth2Authentication.class) {
try {
Object o = parse(parser);
if (o == null) {
return null;
} else if (o instanceof OAuth2Authentication) {
return (T) o;
}
JSONObject jsonObject = (JSONObject) o;
OAuth2Request request = parseOAuth2Request(jsonObject);
//判断json节点userAuthentication的类型,根据类型动态取值
//UsernamePasswordAuthenticationToken 密码模式/授权码模式下,存储类型为UsernamePasswordAuthenticationToken
//PreAuthenticatedAuthenticationToken 刷新token模式下,存储类型为PreAuthenticatedAuthenticationToken
Object autoType = jsonObject.get("userAuthentication");
return (T) new OAuth2Authentication(request, jsonObject.getObject("userAuthentication", (Type) autoType.getClass()));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
return null;
}
private OAuth2Request parseOAuth2Request(JSONObject jsonObject) {
JSONObject json = jsonObject.getObject("oAuth2Request", JSONObject.class);
Map<String, String> requestParameters = json.getObject("requestParameters", Map.class);
String clientId = json.getString("clientId");
String grantType = json.getString("grantType");
String redirectUri = json.getString("redirectUri");
Boolean approved = json.getBoolean("approved");
Set<String> responseTypes = json
.getObject("responseTypes", new TypeReference<HashSet<String>>() {
});
Set<String> scope = json.getObject("scope", new TypeReference<HashSet<String>>() {
});
Set<String> authorities = json.getObject("authorities", new TypeReference<HashSet<String>>() {
});
Set<GrantedAuthority> grantedAuthorities = new HashSet<>(0);
if (authorities != null && !authorities.isEmpty()) {
authorities.forEach(s -> grantedAuthorities.add(new SimpleGrantedAuthority(s)));
}
Set<String> resourceIds = json
.getObject("resourceIds", new TypeReference<HashSet<String>>() {
});
Map<String, Serializable> extensions = json
.getObject("extensions", new TypeReference<HashMap<String, Serializable>>() {
});
OAuth2Request request = new OAuth2Request(requestParameters, clientId,
grantedAuthorities, approved, scope, resourceIds, redirectUri, responseTypes, extensions);
TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scope, grantType);
request.refresh(tokenRequest);
return request;
}
@Override
public int getFastMatchToken() {
return 0;
}
private Object parse(DefaultJSONParser parse) {
JSONObject object = new JSONObject(parse.lexer.isEnabled(Feature.OrderedField));
Object parsedObject = parse.parseObject((Map) object);
if (parsedObject instanceof JSONObject) {
return (JSONObject) parsedObject;
} else if (parsedObject instanceof OAuth2Authentication) {
return parsedObject;
} else {
return parsedObject == null ? null : new JSONObject((Map) parsedObject);
}
}
}
复制代码
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。