终于要折腾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 {@Autowiredprivate RedisConnectionFactory connectionFactory;public static Oauth2Util autowiredStatic;@PostConstructpublic 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的keyString 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();}}
}