终于要折腾oauth2了,感觉平常顺便玩玩还真没什么难度,但对于一些定制功能,什么N种账号类型,什么自定义返回体之类云云。浪费个几小时弄出下面一玩意,算是补充一下知识,在网上搜了一圈感觉也别人说--让某个账号token过期(带redis)。
打开工具看到那几个存在redis的令牌,顺便删一个,要不登录不了,要不访问不了,删不全就是麻烦,让他自己带token访问自己登出倒是简单,但对于管理权限系统就需求就不够了,就好像我要一个账号没有权限登录,但这个账号已经获取到token了,token没过期之前他还是有他本来该有的权限去操作。。。直接干掉token,让他什么都做不了。我稍微封装了一下工具,只要带着账号的基本信息就可以删除(username,scope,client_id)。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeSet;
/**
* 玩转oauth2 工具
*/
@Component
public class Oauth2Util {
@Autowired
private RedisConnectionFactory connectionFactory;
public static Oauth2Util autowiredStatic;
@PostConstruct
public void init() {
autowiredStatic = this;
autowiredStatic.connectionFactory = this.connectionFactory;
}
private static JdkSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
/**
* 根据username,client_id和scope获取该用户的auth_to_access的key值
*
* @param name
* @param client_id
* @param scope
* @return
*/
public static String getAuthToAccess(String name, String client_id, String scope) {
String tempdd = null;
Map<String, String> values = new LinkedHashMap();
values.put("username", name.toUpperCase());
values.put("client_id", client_id);
values.put("scope", OAuth2Utils.formatParameterList(new TreeSet(Collections.singleton(scope))));
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] bytes = digest.digest(values.toString().getBytes("UTF-8"));
tempdd = String.format("%032x", new BigInteger(1, bytes));
} catch (NoSuchAlgorithmException var4) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).", var4);
} catch (UnsupportedEncodingException var5) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).", var5);
}
return tempdd;
}
/**
* 清理指定账号的token,让其token强行删除,无法访问。
*
* @param name
* @param client_id
* @param scope
*/
public static void removeTokenAccess(String name, String client_id, String scope) {
//首先获取auth_to_access的key
String key = getAuthToAccess(name, client_id, scope);
//再通过key获取到当前的令牌信息
byte[] serializedKey7 = serializationStrategy.serialize("auth_to_access:" + key);
RedisConnection conn = autowiredStatic.connectionFactory.getConnection();
byte[] bytes = null;
try {
bytes = conn.get(serializedKey7);
conn.del(serializedKey7);
} finally {
conn.close();
}
OAuth2AccessToken accessToken = serializationStrategy.deserialize(bytes,
OAuth2AccessToken.class);
if(accessToken==null){
return;
}
//再删除令牌信息
byte[] serializedKey = serializationStrategy.serialize("access:" + accessToken.getValue());
byte[] serializedKey2 = serializationStrategy.serialize("access_to_refresh:" + accessToken.getValue());
byte[] serializedKey3 = serializationStrategy.serialize("auth:" + accessToken.getValue());
byte[] serializedKey4 = serializationStrategy.serialize("refresh:" + accessToken.getRefreshToken());
byte[] serializedKey5 = serializationStrategy.serialize("refresh_auth:" + accessToken.getRefreshToken());
byte[] serializedKey6 = serializationStrategy.serialize("refresh_to_access:" + accessToken.getRefreshToken());
conn = autowiredStatic.connectionFactory.getConnection();
try {
conn.del(serializedKey7);
conn.del(serializedKey);
conn.del(serializedKey2);
conn.del(serializedKey3);
conn.del(serializedKey4);
conn.del(serializedKey5);
conn.del(serializedKey6);
} finally {
conn.close();
}
}
}