From 4b6e2e02c0da979376428b4bdaf1cb409003edfe Mon Sep 17 00:00:00 2001
From: Hansin1997 <845612500@qq.com>
Date: Sat, 13 Mar 2021 12:28:25 +0800
Subject: [PATCH] =?UTF-8?q?v1.0.4-alpha-3:=20=E7=A6=81=E7=94=A8=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E4=BB=A5=E5=8F=8A=E5=88=A0=E9=99=A4=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=90=8C=E6=97=B6=E5=88=A0=E9=99=A4=E5=85=B6?=
=?UTF-8?q?=E6=89=80=E6=9C=89=20AccessToken=20=E5=92=8C=20RefreshToken?=
=?UTF-8?q?=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
auth-core/pom.xml | 2 +-
auth-service/pom.xml | 2 +-
.../components/TokenConfiguration.java | 5 +-
.../controllers/resources/UserResource.java | 20 ++++++++
.../oauth/EnhancedRedisTokenStore.java | 50 ++++++++++++++++++-
pom.xml | 2 +-
6 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/auth-core/pom.xml b/auth-core/pom.xml
index c5e32355..d1f80390 100644
--- a/auth-core/pom.xml
+++ b/auth-core/pom.xml
@@ -5,7 +5,7 @@
cn.dustlight.auth
auth-parent
- 1.0.4-alpha-2
+ 1.0.4-alpha-3
../pom.xml
auth-core
diff --git a/auth-service/pom.xml b/auth-service/pom.xml
index d69428d8..aedfc910 100644
--- a/auth-service/pom.xml
+++ b/auth-service/pom.xml
@@ -5,7 +5,7 @@
cn.dustlight.auth
auth-parent
- 1.0.4-alpha-2
+ 1.0.4-alpha-3
../pom.xml
auth-service
diff --git a/auth-service/src/main/java/cn/dustlight/auth/configurations/components/TokenConfiguration.java b/auth-service/src/main/java/cn/dustlight/auth/configurations/components/TokenConfiguration.java
index bf6a822e..aac9d17a 100644
--- a/auth-service/src/main/java/cn/dustlight/auth/configurations/components/TokenConfiguration.java
+++ b/auth-service/src/main/java/cn/dustlight/auth/configurations/components/TokenConfiguration.java
@@ -31,8 +31,9 @@ public RedisTokenStore authTokenStore(@Autowired RedisConnectionFactory redisCon
@Bean("enhancedTokenStore")
@ConditionalOnMissingBean(name = "enhancedTokenStore")
- public EnhancedRedisTokenStore enhancedRedisTokenStore(@Autowired RedisConnectionFactory redisConnectionFactory) {
- return new EnhancedRedisTokenStore(redisConnectionFactory);
+ public EnhancedRedisTokenStore enhancedRedisTokenStore(@Autowired RedisConnectionFactory redisConnectionFactory,
+ @Autowired RedisTokenStore redisTokenStore) {
+ return new EnhancedRedisTokenStore(redisConnectionFactory, redisTokenStore);
}
@Bean("authApprovalStore")
diff --git a/auth-service/src/main/java/cn/dustlight/auth/controllers/resources/UserResource.java b/auth-service/src/main/java/cn/dustlight/auth/controllers/resources/UserResource.java
index 79ba61f8..ffc054c8 100644
--- a/auth-service/src/main/java/cn/dustlight/auth/controllers/resources/UserResource.java
+++ b/auth-service/src/main/java/cn/dustlight/auth/controllers/resources/UserResource.java
@@ -5,6 +5,7 @@
import cn.dustlight.auth.entities.DefaultUser;
import cn.dustlight.auth.entities.DefaultUserRole;
import cn.dustlight.auth.entities.User;
+import cn.dustlight.auth.services.oauth.EnhancedRedisTokenStore;
import cn.dustlight.auth.services.storages.StorageHandler;
import cn.dustlight.auth.services.UserService;
import cn.dustlight.auth.util.Constants;
@@ -53,6 +54,9 @@ public class UserResource {
@Autowired
protected StorageHandler storageHandler;
+ @Autowired
+ protected EnhancedRedisTokenStore enhancedRedisTokenStore;
+
/**
* 判断 Client 与用户是否拥有某权限。
*/
@@ -101,12 +105,20 @@ public User createUser(@RequestParam(name = "username") String username,
@DeleteMapping("users/{uid}")
@io.swagger.v3.oas.annotations.Operation(summary = "删除用户(永久删除)", description = "应用和用户需要 DELETE_USER 权限。")
public void deleteUser(@PathVariable Long uid) {
+ DefaultUser user = userService.loadUser(uid);
+ if (user == null)
+ ErrorEnum.USER_NOT_FOUND.throwException();
userService.deleteUsers(Arrays.asList(uid));
try {
storageHandler.remove(generateAvatarKey(uid));
} catch (Exception e) {
ErrorEnum.DELETE_USER_AVATAR_FAIL.details(e.getMessage());
}
+ try {
+ enhancedRedisTokenStore.deleteUserToken(user.getUsername());
+ } catch (IOException e) {
+ ErrorEnum.DELETE_USER_TOKEN_FAIL.throwException();
+ }
logger.debug(String.format("删除用户: [%s] ", uid));
}
@@ -170,6 +182,14 @@ public void updateUserExpiredAt(@PathVariable Long uid, @RequestParam Date expir
@Operation(summary = "设置用户封禁或解封", description = "封禁或解封用户。应用和用户需拥有 LOCK_USER 权限。")
public void updateUserEnabled(@PathVariable Long uid, @RequestParam Boolean enabled) {
userService.updateEnabled(Arrays.asList(uid), enabled);
+ if(!enabled){
+ DefaultUser user = userService.loadUser(uid);
+ try {
+ enhancedRedisTokenStore.deleteUserToken(user.getUsername());
+ } catch (IOException e) {
+ ErrorEnum.DELETE_USER_TOKEN_FAIL.throwException();
+ }
+ }
}
@PreAuthorize("(#oauth2.client or hasAnyAuthority('WRITE_USER_EMAIL')) and #oauth2.clientHasRole('WRITE_USER_EMAIL')")
diff --git a/auth-service/src/main/java/cn/dustlight/auth/services/oauth/EnhancedRedisTokenStore.java b/auth-service/src/main/java/cn/dustlight/auth/services/oauth/EnhancedRedisTokenStore.java
index f2bba656..0ac977ab 100644
--- a/auth-service/src/main/java/cn/dustlight/auth/services/oauth/EnhancedRedisTokenStore.java
+++ b/auth-service/src/main/java/cn/dustlight/auth/services/oauth/EnhancedRedisTokenStore.java
@@ -1,19 +1,36 @@
package cn.dustlight.auth.services.oauth;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
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.DefaultOAuth2AccessToken;
+import org.springframework.security.oauth2.common.OAuth2RefreshToken;
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 java.io.IOException;
+import java.util.Set;
+
public class EnhancedRedisTokenStore {
private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:";
+
+ private static final String USERNAME_TO_ACCESS = "uname_to_access:";
+
private RedisConnectionFactory redisConnectionFactory;
+ private RedisTokenStore redisTokenStore;
private String prefix = "";
+ private static final Log logger = LogFactory.getLog(EnhancedRedisTokenStore.class);
+
private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy();
- public EnhancedRedisTokenStore(RedisConnectionFactory connectionFactory) {
+ public EnhancedRedisTokenStore(RedisConnectionFactory connectionFactory, RedisTokenStore redisTokenStore) {
+ this.redisTokenStore = redisTokenStore;
this.redisConnectionFactory = connectionFactory;
}
@@ -29,6 +46,14 @@ protected byte[] serializeKey(String key) {
return serializationStrategy.serialize(prefix + key);
}
+ protected String deserializeKey(byte[] bytes) {
+ return serializationStrategy.deserializeString(bytes);
+ }
+
+ protected T deserialize(byte[] bytes, Class clazz) {
+ return serializationStrategy.deserialize(bytes, clazz);
+ }
+
protected RedisConnection getConnection() {
return this.redisConnectionFactory.getConnection();
}
@@ -38,4 +63,27 @@ public Long countClientToken(String clientId) {
return conn.setCommands().sCard(serializeKey(CLIENT_ID_TO_ACCESS + clientId));
}
}
+
+ public void deleteUserToken(String username) throws IOException {
+ try (RedisConnection conn = getConnection()) {
+ try (Cursor cursor = conn.keyCommands().scan(ScanOptions.scanOptions()
+ .match(USERNAME_TO_ACCESS + "*:" + username)
+ .count(Long.MAX_VALUE)
+ .build())) {
+ cursor.forEachRemaining(bytes -> {
+ String key = deserializeKey(bytes);
+ Set tokenSet = conn.sMembers(bytes);
+ if (tokenSet == null)
+ return;
+ tokenSet.forEach(tokenBytes -> {
+ DefaultOAuth2AccessToken accessToken = deserialize(tokenBytes, DefaultOAuth2AccessToken.class);
+ redisTokenStore.removeAccessToken(accessToken);
+ OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
+ if (refreshToken != null)
+ redisTokenStore.removeRefreshToken(refreshToken);
+ });
+ });
+ }
+ }
+ }
}
diff --git a/pom.xml b/pom.xml
index 86e93575..814e0b6c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
cn.dustlight.auth
auth-parent
auth-parent
- 1.0.4-alpha-2
+ 1.0.4-alpha-3
Parent project of OAuth2 Server based on Spring Cloud Security