1.项目架构
2.自己对 TokenStore 的 redis实现
package com.enterprise.auth.config;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class MyRedisTokenStore 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();
private RedisTokenStoreSerializationStrategy serializationStrategy = new MyRedisTokenStoreSerializationStrategy();
private String prefix = "";
private Method redisConnectionSet_2_0;
public MyRedisTokenStore(RedisConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
if (springDataRedis_2_0) {
this.loadRedisConnectionMethods_2_0();
}
}
public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) {
this.authenticationKeyGenerator = authenticationKeyGenerator;
}
public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) {
this.serializationStrategy = serializationStrategy;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
private void loadRedisConnectionMethods_2_0() {
this.redisConnectionSet_2_0 = ReflectionUtils.findMethod(RedisConnection.class, "set", new Class[]{byte[].class, byte[].class});
}
private RedisConnection getConnection() {
return this.connectionFactory.getConnection();
}
private byte[] serialize(Object object) {
return this.serializationStrategy.serialize(object);
}
private byte[] serializeKey(String object) {
return this.serialize(this.prefix + object);
}
private OAuth2AccessToken deserializeAccessToken(byte[] bytes) {
return (OAuth2AccessToken)this.serializationStrategy.deserialize(bytes, OAuth2AccessToken.class);
}
private OAuth2Authentication deserializeAuthentication(byte[] bytes) {
return (OAuth2Authentication)this.serializationStrategy.deserialize(bytes, OAuth2Authentication.class);
}
private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) {
return (OAuth2RefreshToken)this.serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class);
}
private byte[] serialize(String string) {
return this.serializationStrategy.serialize(string);
}
private String deserializeString(byte[] bytes) {
return this.serializationStrategy.deserializeString(bytes);
}
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
String key = this.authenticationKeyGenerator.extractKey(authentication);
byte[] serializedKey = this.serializeKey("auth_to_access:" + key);
byte[] bytes = null;
RedisConnection conn = this.getConnection();
try {
bytes = conn.get(serializedKey);
} finally {
conn.close();
}
OAuth2AccessToken accessToken = this.deserializeAccessToken(bytes);
if (accessToken != null) {
OAuth2Authentication storedAuthentication = this.readAuthentication(accessToken.getValue());
if (storedAuthentication == null || !key.equals(this.authenticationKeyGenerator.extractKey(storedAuthentication))) {
this.storeAccessToken(accessToken, authentication);
}
}
return accessToken;
}
public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
return this.readAuthentication(token.getValue());
}
public OAuth2Authentication readAuthentication(String token) {
byte[] bytes = null;
RedisConnection conn = this.getConnection();
try {
bytes = conn.get(this.serializeKey("auth:" + token));
} finally {
conn.close();
}
OAuth2Authentication var4 = this.deserializeAuthentication(bytes);
return var4;
}
public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
return this.readAuthenticationForRefreshToken(token.getValue());
}
public OAuth2Authentication readAuthenticationForRefreshToken(String token) {
RedisConnection conn = this.getConnection();
OAuth2Authentication var5;
try {
byte[] bytes = conn.get(this.serializeKey("refresh_auth:" + token));
OAuth2Authentication auth = this.deserializeAuthentication(bytes);
var5 = auth;
} finally {
conn.close();
}
return var5;
}
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
byte[] serializedAccessToken = this.serialize((Object)token);
byte[] serializedAuth = this.serialize((Object)authentication);
byte[] accessKey = this.serializeKey("access:" + token.getValue());
byte[] authKey = this.serializeKey("auth:" + token.getValue());
byte[] authToAccessKey = this.serializeKey("auth_to_access:" + this.authenticationKeyGenerator.extractKey(authentication));
byte[] approvalKey = this.serializeKey("uname_to_access:" + getApprovalKey(authentication));
byte[] clientId = this.serializeKey("client_id_to_access:" + authentication.getOAuth2Request().getClientId());
RedisConnection conn = this.getConnection();
try {
conn.openPipeline();
if (springDataRedis_2_0) {
try {
this.redisConnectionSet_2_0.invoke(conn, accessKey, serializedAccessToken);
this.redisConnectionSet_2_0.invoke(conn, authKey, serializedAuth);
this.redisConnectionSet_2_0.invoke(conn, authToAccessKey, serializedAccessToken);
} catch (Exception var24) {
throw new RuntimeException(var24);
}
} else {
conn.set(accessKey, serializedAccessToken);
conn.set(authKey, serializedAuth);
conn.set(authToAccessKey, serializedAccessToken);
}
if (!authentication.isClientOnly()) {
conn.sAdd(approvalKey, new byte[][]{serializedAccessToken});
}
conn.sAdd(clientId, new byte[][]{serializedAccessToken});
if (token.getExpiration() != null) {
int seconds = token.getExpiresIn();
conn.expire(accessKey, (long)seconds);
conn.expire(authKey, (long)seconds);
conn.expire(authToAccessKey, (long)seconds);
conn.expire(clientId, (long)seconds);
conn.expire(approvalKey, (long)seconds);
}
OAuth2RefreshToken refreshToken = token.getRefreshToken();
if (refreshToken != null && refreshToken.getValue() != null) {
byte[] refresh = this.serialize(token.getRefreshToken().getValue());
byte[] auth = this.serialize(token.getValue());
byte[] refreshToAccessKey = this.serializeKey("refresh_to_access:" + token.getRefreshToken().getValue());
byte[] accessToRefreshKey = this.serializeKey("access_to_refresh:" + token.getValue());
if (springDataRedis_2_0) {
try {
this.redisConnectionSet_2_0.invoke(conn, refreshToAccessKey, auth);
this.redisConnectionSet_2_0.invoke(conn, accessToRefreshKey, refresh);
} catch (Exception var23) {
throw new RuntimeException(var23);
}
} else {
conn.set(refreshToAccessKey, auth);
conn.set(accessToRefreshKey, refresh);
}
if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken)refreshToken;
Date expiration = expiringRefreshToken.getExpiration();
if (expiration != null) {
int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L).intValue();
conn.expire(refreshToAccessKey, (long)seconds);
conn.expire(accessToRefreshKey, (long)seconds);
}
}
}
conn.closePipeline();
} finally {
conn.close();
}
}
private static String getApprovalKey(OAuth2Authentication authentication) {
String userName = authentication.getUserAuthentication() == null ? "" : authentication.getUserAuthentication().getName();
return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName);
}
private static String getApprovalKey(String clientId, String userName) {
return clientId + (userName == null ? "" : ":" + userName);
}
public void removeAccessToken(OAuth2AccessToken accessToken) {
this.removeAccessToken(accessToken.getValue());
}
public OAuth2AccessToken readAccessToken(String tokenValue) {
byte[] key = this.serializeKey("access:" + tokenValue);
byte[] bytes = null;
RedisConnection conn = this.getConnection();
try {
bytes = conn.get(key);
} finally {
conn.close();
}
OAuth2AccessToken var5 = this.deserializeAccessToken(bytes);
return var5;
}
public void removeAccessToken(String tokenValue) {
byte[] accessKey = this.serializeKey("access:" + tokenValue);
byte[] authKey = this.serializeKey("auth:" + tokenValue);
byte[] accessToRefreshKey = this.serializeKey("access_to_refresh:" + tokenValue);
RedisConnection conn = this.getConnection();
try {
conn.openPipeline();
conn.get(accessKey);
conn.get(authKey);
conn.del(new byte[][]{accessKey});
conn.del(new byte[][]{accessToRefreshKey});
conn.del(new byte[][]{authKey});
List
3.自定义序列化类
package com.enterprise.auth.config;
import com.google.gson.Gson;
import org.springframework.security.oauth2.provider.token.store.redis.BaseRedisTokenStoreSerializationStrategy;
import java.nio.charset.StandardCharsets;
import java.util.Map;
public class MyRedisTokenStoreSerializationStrategy extends BaseRedisTokenStoreSerializationStrategy {
@Override
//反序列化内部
protected T deserializeInternal(byte[] bytes, Class aClass) {
String s = new String(bytes);
Gson gson = new Gson();
return gson.fromJson(s,aClass);
}
@Override
//反序列化字符串内部
protected String deserializeStringInternal(byte[] bytes) {
return new String(bytes);
}
@Override
//序列化内部
protected byte[] serializeInternal(Object o) {
Gson gson = new Gson();
String json = gson.toJson(o);
return json.getBytes(StandardCharsets.UTF_8);
}
@Override
//序列化内部
protected byte[] serializeInternal(String s) {
return s.getBytes(StandardCharsets.UTF_8);
}
}
4.配置使用redis类型的 TokenStore
package com.enterprise.auth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
public class MyRedisTokenStoreConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore tokenStore() {
MyRedisTokenStore redisTokenStore = new MyRedisTokenStore(redisConnectionFactory);
return redisTokenStore;
}
}
5.完成认证模块的编写后,测试登录
json已经保存在数据库了
但是!!!!!,保存没问题,取出来的时候就有问题了,把这三个文件复制到资源服务器,让资源服务器也用MyRedisTokenStore 的方式读取权限信息.
然后访问,到json权限信息转成实体类的时候,就有问题了,各种各样oauth2 中的数据实体类,没有构造方法,无法创建对象,先转成map在手动新建对象同样不行,
redis中的配置已经读到了
但是需要实例化的对象类路径,这么长一串,没有构造方法,无法新建对象.
报错>>>
结束<<<<<<<<