Browse Source

增加OAuth2GrantedEvent事件

zhouhao 2 years ago
parent
commit
ffb0e24acc

+ 1 - 0
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java

@@ -40,4 +40,5 @@ public interface AccessTokenManager {
      */
     Mono<AccessToken> refreshAccessToken(String clientId, String refreshToken);
 
+    Mono<Void> removeToken(String clientId,String token);
 }

+ 6 - 3
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java

@@ -21,6 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
@@ -64,15 +65,17 @@ public class OAuth2ServerAutoConfiguration {
         @Bean
         @ConditionalOnMissingBean
         public ClientCredentialGranter clientCredentialGranter(ReactiveAuthenticationManager authenticationManager,
-                                                               AccessTokenManager accessTokenManager) {
-            return new DefaultClientCredentialGranter(authenticationManager, accessTokenManager);
+                                                               AccessTokenManager accessTokenManager,
+                                                               ApplicationEventPublisher eventPublisher) {
+            return new DefaultClientCredentialGranter(authenticationManager, accessTokenManager,eventPublisher);
         }
 
         @Bean
         @ConditionalOnMissingBean
         public AuthorizationCodeGranter authorizationCodeGranter(AccessTokenManager tokenManager,
+                                                                 ApplicationEventPublisher eventPublisher,
                                                                  ReactiveRedisConnectionFactory redisConnectionFactory) {
-            return new DefaultAuthorizationCodeGranter(tokenManager, redisConnectionFactory);
+            return new DefaultAuthorizationCodeGranter(tokenManager,eventPublisher, redisConnectionFactory);
         }
 
         @Bean

+ 26 - 8
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranter.java

@@ -4,13 +4,16 @@ import lombok.AllArgsConstructor;
 import org.hswebframework.web.authorization.Authentication;
 import org.hswebframework.web.id.IDGenerator;
 import org.hswebframework.web.oauth2.ErrorType;
+import org.hswebframework.web.oauth2.GrantType;
 import org.hswebframework.web.oauth2.OAuth2Constants;
 import org.hswebframework.web.oauth2.OAuth2Exception;
 import org.hswebframework.web.oauth2.server.AccessToken;
 import org.hswebframework.web.oauth2.server.AccessTokenManager;
 import org.hswebframework.web.oauth2.server.OAuth2Client;
 import org.hswebframework.web.oauth2.server.ScopePredicate;
+import org.hswebframework.web.oauth2.server.event.OAuth2GrantedEvent;
 import org.hswebframework.web.oauth2.server.utils.OAuth2ScopeUtils;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
 import org.springframework.data.redis.core.ReactiveRedisOperations;
 import org.springframework.data.redis.core.ReactiveRedisTemplate;
@@ -25,11 +28,15 @@ public class DefaultAuthorizationCodeGranter implements AuthorizationCodeGranter
 
     private final AccessTokenManager accessTokenManager;
 
+    private final ApplicationEventPublisher eventPublisher;
+
     private final ReactiveRedisOperations<String, AuthorizationCodeCache> redis;
 
     @SuppressWarnings("all")
-    public DefaultAuthorizationCodeGranter(AccessTokenManager accessTokenManager, ReactiveRedisConnectionFactory connectionFactory) {
-        this(accessTokenManager, new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext
+    public DefaultAuthorizationCodeGranter(AccessTokenManager accessTokenManager,
+                                           ApplicationEventPublisher eventPublisher,
+                                           ReactiveRedisConnectionFactory connectionFactory) {
+        this(accessTokenManager, eventPublisher, new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext
                 .newSerializationContext()
                 .key((RedisSerializer) RedisSerializer.string())
                 .value(RedisSerializer.java())
@@ -75,16 +82,27 @@ public class DefaultAuthorizationCodeGranter implements AuthorizationCodeGranter
                 .map(this::getRedisKey)
                 .flatMap(redis.opsForValue()::get)
                 .switchIfEmpty(Mono.error(() -> new OAuth2Exception(ErrorType.ILLEGAL_CODE)))
-                .flatMap(cache -> redis
-                        .opsForValue()
-                        .delete(getRedisKey(cache.getCode()))
-                        .thenReturn(cache))
+                //移除code
+                .flatMap(cache -> redis.opsForValue().delete(getRedisKey(cache.getCode())).thenReturn(cache))
                 .flatMap(cache -> {
                     if (!request.getClient().getClientId().equals(cache.getClientId())) {
                         return Mono.error(new OAuth2Exception(ErrorType.ILLEGAL_CLIENT_ID));
                     }
-                    return accessTokenManager.createAccessToken(cache.getClientId(), cache.getAuthentication(), false);
-                });
+                    return accessTokenManager
+                            .createAccessToken(cache.getClientId(), cache.getAuthentication(), false)
+                            .flatMap(token -> new OAuth2GrantedEvent(request.getClient(),
+                                                                     token,
+                                                                     cache.getAuthentication(),
+                                                                     cache.getScope(),
+                                                                     GrantType.authorization_code,
+                                                                     request.getParameters())
+                                    .publish(eventPublisher)
+                                    .onErrorResume(err -> accessTokenManager
+                                            .removeToken(cache.getClientId(), token.getAccessToken())
+                                            .then(Mono.error(err)))
+                                    .thenReturn(token));
+                })
+                ;
 
     }
 }

+ 19 - 1
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/credential/DefaultClientCredentialGranter.java

@@ -2,9 +2,12 @@ package org.hswebframework.web.oauth2.server.credential;
 
 import lombok.AllArgsConstructor;
 import org.hswebframework.web.authorization.ReactiveAuthenticationManager;
+import org.hswebframework.web.oauth2.GrantType;
 import org.hswebframework.web.oauth2.server.AccessToken;
 import org.hswebframework.web.oauth2.server.AccessTokenManager;
 import org.hswebframework.web.oauth2.server.OAuth2Client;
+import org.hswebframework.web.oauth2.server.event.OAuth2GrantedEvent;
+import org.springframework.context.ApplicationEventPublisher;
 import reactor.core.publisher.Mono;
 
 @AllArgsConstructor
@@ -14,6 +17,8 @@ public class DefaultClientCredentialGranter implements ClientCredentialGranter {
 
     private final AccessTokenManager accessTokenManager;
 
+    private final ApplicationEventPublisher eventPublisher;
+
     @Override
     public Mono<AccessToken> requestToken(ClientCredentialRequest request) {
 
@@ -21,6 +26,19 @@ public class DefaultClientCredentialGranter implements ClientCredentialGranter {
 
         return authenticationManager
                 .getByUserId(client.getUserId())
-                .flatMap(auth -> accessTokenManager.createAccessToken(client.getClientId(), auth, true));
+                .flatMap(auth -> accessTokenManager
+                        .createAccessToken(client.getClientId(), auth, true)
+                        .flatMap(token -> new OAuth2GrantedEvent(client,
+                                                                 token,
+                                                                 auth,
+                                                                 "*",
+                                                                 GrantType.client_credentials,
+                                                                 request.getParameters())
+                                .publish(eventPublisher)
+                                .onErrorResume(err -> accessTokenManager
+                                        .removeToken(client.getClientId(), token.getAccessToken())
+                                        .then(Mono.error(err)))
+                                .thenReturn(token))
+                );
     }
 }

+ 32 - 0
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/event/OAuth2GrantedEvent.java

@@ -0,0 +1,32 @@
+package org.hswebframework.web.oauth2.server.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.hswebframework.web.authorization.Authentication;
+import org.hswebframework.web.event.DefaultAsyncEvent;
+import org.hswebframework.web.oauth2.server.AccessToken;
+import org.hswebframework.web.oauth2.server.OAuth2Client;
+
+import java.util.Map;
+
+/**
+ * OAuth2授权成功事件
+ *
+ * @author zhouhao
+ * @since 4.0.15
+ */
+@Getter
+@AllArgsConstructor
+public class OAuth2GrantedEvent extends DefaultAsyncEvent {
+    private final OAuth2Client client;
+
+    private final AccessToken accessToken;
+
+    private final Authentication authentication;
+
+    private final String scope;
+
+    private final String grantType;
+
+    private final Map<String, String> parameters;
+}

+ 10 - 0
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java

@@ -178,4 +178,14 @@ public class RedisAccessTokenManager implements AccessTokenManager {
                 });
 
     }
+
+    @Override
+    public Mono<Void> removeToken(String clientId, String token) {
+
+        return Flux
+                .merge(userTokenManager.signOutByToken(token),
+                       tokenRedis.delete(createSingletonTokenRedisKey(clientId)),
+                       tokenRedis.delete(createTokenRedisKey(token)))
+                .then();
+    }
 }

+ 2 - 0
hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/web/OAuth2AuthorizeController.java

@@ -19,7 +19,9 @@ import org.hswebframework.web.oauth2.server.OAuth2GrantService;
 import org.hswebframework.web.oauth2.server.code.AuthorizationCodeRequest;
 import org.hswebframework.web.oauth2.server.code.AuthorizationCodeTokenRequest;
 import org.hswebframework.web.oauth2.server.credential.ClientCredentialRequest;
+import org.hswebframework.web.oauth2.server.event.OAuth2GrantedEvent;
 import org.hswebframework.web.oauth2.server.refresh.RefreshTokenRequest;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;

+ 2 - 1
hsweb-authorization/hsweb-authorization-oauth2/src/test/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranterTest.java

@@ -7,6 +7,7 @@ import org.hswebframework.web.oauth2.server.OAuth2Client;
 import org.hswebframework.web.oauth2.server.RedisHelper;
 import org.hswebframework.web.oauth2.server.impl.RedisAccessTokenManager;
 import org.junit.Test;
+import org.springframework.context.support.StaticApplicationContext;
 import reactor.test.StepVerifier;
 
 import java.util.Collections;
@@ -20,7 +21,7 @@ public class DefaultAuthorizationCodeGranterTest {
     public void testRequestToken() {
 
         DefaultAuthorizationCodeGranter codeGranter = new DefaultAuthorizationCodeGranter(
-                new RedisAccessTokenManager(RedisHelper.factory), RedisHelper.factory
+                new RedisAccessTokenManager(RedisHelper.factory), new StaticApplicationContext(), RedisHelper.factory
         );
 
         OAuth2Client client = new OAuth2Client();