ソースを参照

#IAZNZS oauth2单点注销没有生效修复

shimingxy 7 ヶ月 前
コミット
4ceaebf80c
16 ファイル変更289 行追加61 行削除
  1. 12 12
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/Session.java
  2. 2 0
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java
  3. 156 0
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/VisitedDto.java
  4. 14 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/InMemorySessionManager.java
  5. 14 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/RedisSessionManager.java
  6. 16 4
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/SessionManagerImpl.java
  7. 2 2
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java
  8. 0 12
      maxkey-core/src/main/java/org/dromara/maxkey/entity/apps/Apps.java
  9. 4 5
      maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/DefaultSingleLogout.java
  10. 4 4
      maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SamlSingleLogout.java
  11. 2 2
      maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SingleLogout.java
  12. 4 10
      maxkey-protocols/maxkey-protocol-cas/src/main/java/org/dromara/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java
  13. 34 0
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java
  14. 7 1
      maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/autoconfigure/Oauth20AutoConfiguration.java
  15. 17 5
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/contorller/LogoutEndpoint.java
  16. 1 2
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/interceptor/SingleSignOnInterceptor.java

+ 12 - 12
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/Session.java

@@ -20,8 +20,8 @@ package org.dromara.maxkey.authn.session;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 import java.util.HashMap;
+import java.util.Map;
 
-import org.dromara.maxkey.entity.apps.Apps;
 import org.dromara.maxkey.web.WebContext;
 import org.springframework.security.core.Authentication;
 
@@ -40,7 +40,7 @@ public class Session implements Serializable{
     
     public Authentication authentication;
     
-    private HashMap<String , Apps> authorizedApps = new HashMap<String , Apps>();
+    Map<String , VisitedDto> visited = new HashMap<>();
     
     public Session() {
         super();
@@ -105,19 +105,19 @@ public class Session implements Serializable{
         this.authentication = authentication;
     }
 
-    public HashMap<String, Apps> getAuthorizedApps() {
-        return authorizedApps;
+    public void visited(VisitedDto visited) {
+        this.visited.put(visited.getAppId(), visited);
     }
 
-    public void setAuthorizedApps(HashMap<String, Apps> authorizedApps) {
-        this.authorizedApps = authorizedApps;
-    }
-    
-    public void setAuthorizedApp(Apps authorizedApp) {
-        this.authorizedApps.put(authorizedApp.getId(), authorizedApp);
-    }
+    public Map<String, VisitedDto> getVisited() {
+		return visited;
+	}
+
+	public void setVisited(Map<String, VisitedDto> visited) {
+		this.visited = visited;
+	}
 
-    @Override
+	@Override
 	public String toString() {
 		StringBuilder builder = new StringBuilder();
 		builder.append("Session [id=");

+ 2 - 0
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java

@@ -39,4 +39,6 @@ public interface SessionManager {
     public int getValiditySeconds();
 
     public void terminate(String sessionId,String userId,String username);
+    
+    public void visited(String sessionId , VisitedDto visited);
 }

+ 156 - 0
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/VisitedDto.java

@@ -0,0 +1,156 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn.session;
+
+import java.io.Serializable;
+
+import org.dromara.maxkey.entity.apps.Apps;
+import org.dromara.maxkey.entity.apps.AppsCasDetails;
+
+public class VisitedDto  implements Serializable{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -6694914707659511202L;
+
+	/**
+	 * appId or client id
+	 */
+	String appId;
+	/**
+	 * protocol
+	 */
+	String protocol;
+	/**
+	 * ticket
+	 */
+	String ticket;
+	/**
+	 * token
+	 */
+	String token;
+	
+	/**
+	 * refreshToken
+	 */
+	String refreshToken;
+	/**
+	 * logoutType
+	 */
+	int logoutType;
+	/**
+	 * logoutUrl
+	 */
+	String logoutUrl;
+	
+	
+	public VisitedDto(AppsCasDetails app,String ticket ) {
+		this.appId = app.getId();
+		this.protocol = app.getProtocol();
+		this.logoutType = app.getLogoutType();
+		this.logoutUrl = app.getLogoutUrl();
+		this.ticket = ticket;
+	}
+	
+	public VisitedDto(Apps app,String ticket ) {
+		this.appId = app.getId();
+		this.protocol = app.getProtocol();
+		this.logoutType = app.getLogoutType();
+		this.logoutUrl = app.getLogoutUrl();
+		this.ticket = ticket;
+	}
+
+	public String getAppId() {
+		return appId;
+	}
+
+	public void setAppId(String appId) {
+		this.appId = appId;
+	}
+
+	public String getProtocol() {
+		return protocol;
+	}
+
+	public void setProtocol(String protocol) {
+		this.protocol = protocol;
+	}
+
+	public String getTicket() {
+		return ticket;
+	}
+
+	public void setTicket(String ticket) {
+		this.ticket = ticket;
+	}
+
+	public String getToken() {
+		return token;
+	}
+
+	public void setToken(String token) {
+		this.token = token;
+	}
+
+	public String getRefreshToken() {
+		return refreshToken;
+	}
+
+	public void setRefreshToken(String refreshToken) {
+		this.refreshToken = refreshToken;
+	}
+
+	public int getLogoutType() {
+		return logoutType;
+	}
+
+	public void setLogoutType(int logoutType) {
+		this.logoutType = logoutType;
+	}
+
+	public String getLogoutUrl() {
+		return logoutUrl;
+	}
+
+	public void setLogoutUrl(String logoutUrl) {
+		this.logoutUrl = logoutUrl;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("VisitedDto [appId=");
+		builder.append(appId);
+		builder.append(", protocol=");
+		builder.append(protocol);
+		builder.append(", ticket=");
+		builder.append(ticket);
+		builder.append(", token=");
+		builder.append(token);
+		builder.append(", refreshToken=");
+		builder.append(refreshToken);
+		builder.append(", logoutType=");
+		builder.append(logoutType);
+		builder.append(", logoutUrl=");
+		builder.append(logoutUrl);
+		builder.append("]");
+		return builder.toString();
+	}
+	
+}

+ 14 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/InMemorySessionManager.java → maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/InMemorySessionManager.java

@@ -15,12 +15,15 @@
  */
  
 
-package org.dromara.maxkey.authn.session;
+package org.dromara.maxkey.authn.session.impl;
 
 import java.time.LocalDateTime;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
+import org.dromara.maxkey.authn.session.Session;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.entity.history.HistoryLogin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -113,4 +116,14 @@ public class InMemorySessionManager implements SessionManager{
 		// not need implement
 	}
 
+	@Override
+	public void visited(String sessionId, VisitedDto visited) {
+		Session session  = this.get(sessionId);
+	    //set token or ticket to Visited , bind user session
+		session.visited(visited);
+		//override the session
+	    this.create(sessionId, session);
+	    _logger.debug("session {} store visited  {} ." , sessionId , visited);
+	}
+
 }

+ 14 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/RedisSessionManager.java → maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/RedisSessionManager.java

@@ -15,11 +15,14 @@
  */
  
 
-package org.dromara.maxkey.authn.session;
+package org.dromara.maxkey.authn.session.impl;
 
 import java.time.LocalDateTime;
 import java.util.List;
 
+import org.dromara.maxkey.authn.session.Session;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.entity.history.HistoryLogin;
 import org.dromara.maxkey.persistence.redis.RedisConnection;
 import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
@@ -135,5 +138,15 @@ public class RedisSessionManager implements SessionManager {
 		// not need implement
 	}
 
+	@Override
+	public void visited(String sessionId, VisitedDto visited) {
+		Session session  = this.get(sessionId);
+	    //set token or ticket to Visited , bind user session
+		session.visited(visited);
+		//override the session
+	    this.create(sessionId, session);
+	    _logger.debug("session {} store visited  {} ." , sessionId , visited);
+		
+	}
 	
 }

+ 16 - 4
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManagerFactory.java → maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/SessionManagerImpl.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.authn.session;
+package org.dromara.maxkey.authn.session.impl;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -24,6 +24,9 @@ import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 
+import org.dromara.maxkey.authn.session.Session;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.constants.ConstsPersistence;
 import org.dromara.maxkey.entity.history.HistoryLogin;
 import org.dromara.maxkey.entity.idm.UserInfo;
@@ -42,9 +45,9 @@ import org.springframework.jdbc.core.RowMapper;
  * @author shimh
  *
  */
-public class SessionManagerFactory implements SessionManager{
+public class SessionManagerImpl implements SessionManager{
 	private static final  Logger _logger = 
-            LoggerFactory.getLogger(SessionManagerFactory.class);
+            LoggerFactory.getLogger(SessionManagerImpl.class);
 	
 	private static final String DEFAULT_DEFAULT_SELECT_STATEMENT = 
 			"select id,sessionid,userId,username,displayname,logintime from mxk_history_login where sessionstatus = 1";
@@ -68,7 +71,7 @@ public class SessionManagerFactory implements SessionManager{
 	
 	private int validitySeconds ;
 	
-	public SessionManagerFactory(int persistence,
+	public SessionManagerImpl(int persistence,
 			 	JdbcTemplate jdbcTemplate,
 	            RedisConnectionFactory redisConnFactory,
 	            int validitySeconds) {
@@ -192,4 +195,13 @@ public class SessionManagerFactory implements SessionManager{
 			return history;
 		}
 	}
+
+	@Override
+	public void visited(String sessionId, VisitedDto visited) {
+		if(isRedis) {
+			redisSessionManager.visited(sessionId,visited);
+		}else {
+			inMemorySessionManager.visited(sessionId,visited);
+		}
+	}
 }

+ 2 - 2
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java

@@ -18,7 +18,7 @@
 package org.dromara.maxkey.autoconfigure;
 
 import org.dromara.maxkey.authn.session.SessionManager;
-import org.dromara.maxkey.authn.session.SessionManagerFactory;
+import org.dromara.maxkey.authn.session.impl.SessionManagerImpl;
 import org.dromara.maxkey.authn.web.HttpSessionListenerAdapter;
 import org.dromara.maxkey.authn.web.SavedRequestAwareAuthenticationSuccessHandler;
 import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
@@ -50,7 +50,7 @@ public class SessionAutoConfiguration  {
             @Value("${maxkey.auth.session.timeout:1800}") int timeout
             ) {
     	_logger.debug("session timeout {}" , timeout);
-        return new SessionManagerFactory(
+        return new SessionManagerImpl(
         		persistence, jdbcTemplate, redisConnFactory,timeout);
     }
 

+ 0 - 12
maxkey-core/src/main/java/org/dromara/maxkey/entity/apps/Apps.java

@@ -170,8 +170,6 @@ public class Apps extends JpaEntity implements Serializable {
 	private String instName;
     
     protected String loginDateTime;
-
-    protected String onlineTicket;
     
     public Apps() {
         super();
@@ -600,14 +598,6 @@ public class Apps extends JpaEntity implements Serializable {
         this.loginDateTime = loginDateTime;
     }
 
-    public String getOnlineTicket() {
-        return onlineTicket;
-    }
-
-    public void setOnlineTicket(String onlineTicket) {
-        this.onlineTicket = onlineTicket;
-    }
-
     public String getAdapterId() {
 		return adapterId;
 	}
@@ -713,8 +703,6 @@ public class Apps extends JpaEntity implements Serializable {
 		builder.append(description);
 		builder.append(", loginDateTime=");
 		builder.append(loginDateTime);
-		builder.append(", onlineTicket=");
-		builder.append(onlineTicket);
 		builder.append("]");
 		return builder.toString();
 	}

+ 4 - 5
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/DefaultSingleLogout.java

@@ -20,22 +20,21 @@ package org.dromara.maxkey.authz.singlelogout;
 import java.util.HashMap;
 import java.util.UUID;
 
-import org.dromara.maxkey.authn.SignPrincipal;
-import org.dromara.maxkey.entity.apps.Apps;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.util.DateUtils;
 import org.springframework.security.core.Authentication;
 
 public class DefaultSingleLogout extends SingleLogout{
 
     @Override
-    public void sendRequest(Authentication authentication,Apps logoutApp) {
+    public void sendRequest(Authentication authentication,VisitedDto visited) {
         HashMap<String,Object> logoutParameters  = new HashMap<String,Object>();
         logoutParameters.put("id",  UUID.randomUUID().toString());
         logoutParameters.put("principal", authentication.getName());
         logoutParameters.put("request",  "logoutRequest");
         logoutParameters.put("issueInstant", DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP));
-        logoutParameters.put("ticket",  ((SignPrincipal)authentication.getPrincipal()).getSessionId());
-        postMessage(logoutApp.getLogoutUrl(),logoutParameters);
+        logoutParameters.put("ticket",   visited.getTicket());
+        postMessage(visited.getLogoutUrl(),logoutParameters);
         
     }
     

+ 4 - 4
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SamlSingleLogout.java

@@ -20,7 +20,7 @@ package org.dromara.maxkey.authz.singlelogout;
 import java.util.HashMap;
 import java.util.UUID;
 
-import org.dromara.maxkey.entity.apps.Apps;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.util.DateUtils;
 import org.springframework.security.core.Authentication;
 
@@ -43,17 +43,17 @@ public class SamlSingleLogout extends SingleLogout{
             + "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>";
 
     @Override
-    public void sendRequest(Authentication authentication,Apps logoutApp) {
+    public void sendRequest(Authentication authentication,VisitedDto visited) {
         String requestMessage = String.format(logoutRequestMessage, 
                 UUID.randomUUID().toString(),
                 DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP),
                 authentication.getName(),
-                logoutApp.getOnlineTicket()
+                visited.getTicket()
                 );
         
         HashMap<String,Object> logoutParameters  = new HashMap<String,Object>();
         logoutParameters.put(LOGOUT_REQUEST_PARAMETER, requestMessage);
-        postMessage(logoutApp.getLogoutUrl(),logoutParameters);
+        postMessage(visited.getLogoutUrl(),logoutParameters);
     }
 
     public SamlSingleLogout() {

+ 2 - 2
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SingleLogout.java

@@ -19,7 +19,7 @@ package org.dromara.maxkey.authz.singlelogout;
 
 import java.util.Map;
 
-import org.dromara.maxkey.entity.apps.Apps;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.web.HttpRequestAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,7 +28,7 @@ import org.springframework.security.core.Authentication;
 public abstract class SingleLogout {
     private static final Logger _logger = LoggerFactory.getLogger(SingleLogout.class);
     
-    public abstract void sendRequest(Authentication authentication,Apps logoutApp) ;
+    public abstract void sendRequest(Authentication authentication,VisitedDto visited) ;
     
     public void postMessage(String url,Map<String, Object> paramMap) {
     	_logger.debug("post logout message to url {}" , url);

+ 4 - 10
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/dromara/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java

@@ -24,7 +24,7 @@ import java.security.Principal;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.dromara.maxkey.authn.session.Session;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.authn.web.AuthorizationUtils;
 import org.dromara.maxkey.authz.cas.endpoint.ticket.CasConstants;
 import org.dromara.maxkey.authz.cas.endpoint.ticket.ServiceTicketImpl;
@@ -155,15 +155,9 @@ public class CasAuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 		if(casDetails.getLogoutType()==LogoutType.BACK_CHANNEL) {
 			_logger.debug("CAS LogoutType BACK_CHANNEL ... ");
 			String sessionId = AuthorizationUtils.getPrincipal().getSessionId();
-			_logger.trace("get session by id {} . ",sessionId);
-		    Session session  = sessionManager.get(sessionId);
-		    _logger.trace("current session {}  ",session);
-		    //set cas ticket as OnlineTicketId
-		    casDetails.setOnlineTicket(ticket);
-		    session.setAuthorizedApp(casDetails);
-		    _logger.trace("session store ticket  {} .",ticket);
-		    sessionManager.create(sessionId, session);
-		    _logger.debug("CAS LogoutType session store ticket to AuthorizedApp .");
+		    VisitedDto visited = new VisitedDto(casDetails,ticket);
+		    sessionManager.visited(sessionId, visited);
+		    _logger.debug("App id {} , name {} , CAS LogoutType BACK_CHANNEL ... " , casDetails.getId(),casDetails.getAppName());
 		}
 		
 		_logger.debug("redirect to CAS Client URL {}" , callbackUrl);

+ 34 - 0
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java

@@ -17,11 +17,15 @@ import java.util.Date;
 import java.util.Set;
 import java.util.UUID;
 
+import org.dromara.maxkey.authn.SignPrincipal;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.authn.session.VisitedDto;
 import org.dromara.maxkey.authz.oauth2.common.DefaultExpiringOAuth2RefreshToken;
 import org.dromara.maxkey.authz.oauth2.common.DefaultOAuth2AccessToken;
 import org.dromara.maxkey.authz.oauth2.common.DefaultOAuth2RefreshToken;
 import org.dromara.maxkey.authz.oauth2.common.ExpiringOAuth2RefreshToken;
 import org.dromara.maxkey.authz.oauth2.common.OAuth2AccessToken;
+import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants;
 import org.dromara.maxkey.authz.oauth2.common.OAuth2RefreshToken;
 import org.dromara.maxkey.authz.oauth2.common.exceptions.InvalidGrantException;
 import org.dromara.maxkey.authz.oauth2.common.exceptions.InvalidScopeException;
@@ -31,7 +35,11 @@ import org.dromara.maxkey.authz.oauth2.provider.ClientRegistrationException;
 import org.dromara.maxkey.authz.oauth2.provider.OAuth2Authentication;
 import org.dromara.maxkey.authz.oauth2.provider.OAuth2Request;
 import org.dromara.maxkey.authz.oauth2.provider.TokenRequest;
+import org.dromara.maxkey.entity.apps.Apps;
 import org.dromara.maxkey.entity.apps.oauth2.provider.ClientDetails;
+import org.dromara.maxkey.persistence.service.AppsService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.core.Authentication;
@@ -54,6 +62,7 @@ import org.springframework.util.Assert;
  */
 public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices,
 		ConsumerTokenServices, InitializingBean {
+	static final  Logger _logger = LoggerFactory.getLogger(DefaultTokenServices.class);
 
 	private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days.
 
@@ -70,6 +79,10 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 	private TokenEnhancer accessTokenEnhancer;
 
 	private AuthenticationManager authenticationManager;
+	
+	private AppsService appsService;
+	
+	private SessionManager sessionManager;
 
 	/**
 	 * Initialize these token services. If no random generator is set, one will be created.
@@ -125,6 +138,18 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 		if (refreshToken != null) {
 			tokenStore.storeRefreshToken(refreshToken, authentication);
 		}
+		//存储oauth、oidc等的token,用户退出时清除
+		if(authentication.getUserAuthentication().getPrincipal() instanceof SignPrincipal principal) {
+			_logger.debug("{}({}) , session {} access for logout clear ",
+					principal.getUsername(),principal.getUserId(),principal.getSessionId());
+			String clientId = authentication.getOAuth2Request().getRequestParameters().get(OAuth2Constants.PARAMETER.CLIENT_ID);
+			_logger.debug("client_id {} token {}",clientId,accessToken);
+			Apps app = appsService.get(clientId, true);
+			VisitedDto visited = new VisitedDto(app,principal.getSessionId());
+			visited.setToken(accessToken.getValue());
+			visited.setRefreshToken(accessToken.getRefreshToken().getValue());
+			sessionManager.visited(principal.getSessionId(), visited);
+		}
 		return accessToken;
 
 	}
@@ -432,4 +457,13 @@ public class DefaultTokenServices implements AuthorizationServerTokenServices, R
 		this.clientDetailsService = clientDetailsService;
 	}
 
+	public void setAppsService(AppsService appsService) {
+		this.appsService = appsService;
+	}
+
+	public void setSessionManager(SessionManager sessionManager) {
+		this.sessionManager = sessionManager;
+	}
+
+	
 }

+ 7 - 1
maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/autoconfigure/Oauth20AutoConfiguration.java

@@ -23,6 +23,7 @@ import java.security.spec.InvalidKeySpecException;
 
 import javax.sql.DataSource;
 
+import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.authz.oauth2.common.OAuth2Constants;
 import org.dromara.maxkey.authz.oauth2.provider.ClientDetailsService;
 import org.dromara.maxkey.authz.oauth2.provider.OAuth2UserDetailsService;
@@ -48,6 +49,7 @@ import org.dromara.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptio
 import org.dromara.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
 import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
 import org.dromara.maxkey.persistence.repository.LoginRepository;
+import org.dromara.maxkey.persistence.service.AppsService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
@@ -259,12 +261,16 @@ public class Oauth20AutoConfiguration implements InitializingBean {
     DefaultTokenServices defaultTokenServices(
             JdbcClientDetailsService oauth20JdbcClientDetailsService,
             TokenStore oauth20TokenStore,
-            OIDCIdTokenEnhancer tokenEnhancer) {
+            OIDCIdTokenEnhancer tokenEnhancer,
+            AppsService appsService,
+            SessionManager sessionManager) {
         DefaultTokenServices tokenServices = new DefaultTokenServices();
         tokenServices.setClientDetailsService(oauth20JdbcClientDetailsService);
         tokenServices.setTokenEnhancer(tokenEnhancer);
         tokenServices.setTokenStore(oauth20TokenStore);
         tokenServices.setSupportRefreshToken(true);
+        tokenServices.setAppsService(appsService);
+        tokenServices.setSessionManager(sessionManager);
         _logger.debug("OAuth 2 Token Services init.");
         return tokenServices;
     }

+ 17 - 5
maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/contorller/LogoutEndpoint.java

@@ -25,6 +25,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.authn.annotation.CurrentUser;
 import org.dromara.maxkey.authn.session.Session;
 import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.authn.session.VisitedDto;
+import org.dromara.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
 import org.dromara.maxkey.authz.singlelogout.DefaultSingleLogout;
 import org.dromara.maxkey.authz.singlelogout.LogoutType;
 import org.dromara.maxkey.authz.singlelogout.SamlSingleLogout;
@@ -32,7 +34,6 @@ import org.dromara.maxkey.authz.singlelogout.SingleLogout;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsProtocols;
 import org.dromara.maxkey.entity.Message;
-import org.dromara.maxkey.entity.apps.Apps;
 import org.dromara.maxkey.entity.idm.UserInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,6 +60,9 @@ public class LogoutEndpoint {
 	@Autowired
     SessionManager sessionManager;
 	
+	@Autowired
+	DefaultTokenServices oauth20TokenServices;
+	
 	/**
 	 * for front end
 	 * @param currentUser
@@ -73,11 +77,12 @@ public class LogoutEndpoint {
  		Session session = sessionManager.get(sessionId);
  		if(session != null) {
  			logger.debug("/logout frontend clean Session id {}",session.getId());
-	 		Set<Entry<String, Apps>> entrySet = session.getAuthorizedApps().entrySet();
+	 		Set<Entry<String, VisitedDto>> entrySet = session.getVisited().entrySet();
 	 
-	        Iterator<Entry<String, Apps>> iterator = entrySet.iterator();
+	        Iterator<Entry<String, VisitedDto>> iterator = entrySet.iterator();
 	        while (iterator.hasNext()) {
-	            Entry<String, Apps> mapEntry = iterator.next();
+	            Entry<String, VisitedDto> mapEntry = iterator.next();
+	            VisitedDto visited = mapEntry.getValue();
 	            logger.debug("App Id : {} , {} " ,  mapEntry.getKey() ,mapEntry.getValue());
 	            if( mapEntry.getValue().getLogoutType() == LogoutType.BACK_CHANNEL){
 	                SingleLogout singleLogout;
@@ -86,7 +91,14 @@ public class LogoutEndpoint {
 	                }else {
 	                    singleLogout = new DefaultSingleLogout();
 	                }
-	                singleLogout.sendRequest(session.getAuthentication(), mapEntry.getValue());
+	                singleLogout.sendRequest(session.getAuthentication(), visited);
+	            }
+	            //oauth , oidc revoke token
+	            if(visited.getProtocol().equalsIgnoreCase(ConstsProtocols.OAUTH20)
+	            		||visited.getProtocol().equalsIgnoreCase(ConstsProtocols.OAUTH21)
+	            		||visited.getProtocol().equalsIgnoreCase(ConstsProtocols.OPEN_ID_CONNECT10)) {
+	            	oauth20TokenServices.revokeToken(visited.getToken());
+	            	logger.debug("revoke token");
 	            }
 	        }
 	        //terminate session

+ 1 - 2
maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/interceptor/SingleSignOnInterceptor.java

@@ -101,8 +101,7 @@ public class SingleSignOnInterceptor  implements AsyncHandlerInterceptor {
 	        		logger.debug("appId {}",appId);
 		        	app = appsService.get(appId,true);
 	        	}else if(requestURI.contains("/authz/oauth/v20/authorize")) {//oauth
-		        	app = appsService.get(
-		        			request.getParameter(OAuth2Constants.PARAMETER.CLIENT_ID),true);
+		        	app = appsService.get(request.getParameter(OAuth2Constants.PARAMETER.CLIENT_ID),true);
 	        	}
 	        }