diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/Session.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/Session.java index aa01b634c..268d90111 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/Session.java +++ b/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 authorizedApps = new HashMap(); + Map visited = new HashMap<>(); public Session() { super(); @@ -105,19 +105,19 @@ public class Session implements Serializable{ this.authentication = authentication; } - public HashMap getAuthorizedApps() { - return authorizedApps; + public void visited(VisitedDto visited) { + this.visited.put(visited.getAppId(), visited); } - public void setAuthorizedApps(HashMap authorizedApps) { - this.authorizedApps = authorizedApps; - } - - public void setAuthorizedApp(Apps authorizedApp) { - this.authorizedApps.put(authorizedApp.getId(), authorizedApp); - } + public Map getVisited() { + return visited; + } - @Override + public void setVisited(Map visited) { + this.visited = visited; + } + + @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Session [id="); diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java index 232d815ac..a9910c3cf 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java +++ b/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); } diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/VisitedDto.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/VisitedDto.java new file mode 100644 index 000000000..890c58a2c --- /dev/null +++ b/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(); + } + +} diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/InMemorySessionManager.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/InMemorySessionManager.java similarity index 86% rename from maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/InMemorySessionManager.java rename to maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/InMemorySessionManager.java index 679a88c80..85228412a 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/InMemorySessionManager.java +++ b/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); + } + } diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/RedisSessionManager.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/RedisSessionManager.java similarity index 87% rename from maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/RedisSessionManager.java rename to maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/RedisSessionManager.java index 5c133e5ad..8ca3618d8 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/RedisSessionManager.java +++ b/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); + + } } diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManagerFactory.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/SessionManagerImpl.java similarity index 91% rename from maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManagerFactory.java rename to maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/impl/SessionManagerImpl.java index 1b1ad9d32..9a8aa0915 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManagerFactory.java +++ b/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); + } + } } diff --git a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java b/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java index 3b848e280..c9c230a7d 100644 --- a/maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java +++ b/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); } diff --git a/maxkey-core/src/main/java/org/dromara/maxkey/entity/apps/Apps.java b/maxkey-core/src/main/java/org/dromara/maxkey/entity/apps/Apps.java index dbdf509e6..ba7802e78 100644 --- a/maxkey-core/src/main/java/org/dromara/maxkey/entity/apps/Apps.java +++ b/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(); } diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/DefaultSingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/DefaultSingleLogout.java index 8b73a375b..7768882b1 100644 --- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/DefaultSingleLogout.java +++ b/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 logoutParameters = new HashMap(); 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); } diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SamlSingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SamlSingleLogout.java index cd9719334..24aba8530 100644 --- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SamlSingleLogout.java +++ b/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{ + "%s"; @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 logoutParameters = new HashMap(); logoutParameters.put(LOGOUT_REQUEST_PARAMETER, requestMessage); - postMessage(logoutApp.getLogoutUrl(),logoutParameters); + postMessage(visited.getLogoutUrl(),logoutParameters); } public SamlSingleLogout() { diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SingleLogout.java index 73720182a..b3407311c 100644 --- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/dromara/maxkey/authz/singlelogout/SingleLogout.java +++ b/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 paramMap) { _logger.debug("post logout message to url {}" , url); diff --git a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/dromara/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java b/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/dromara/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java index 2162ec16d..eda1435e6 100644 --- a/maxkey-protocols/maxkey-protocol-cas/src/main/java/org/dromara/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java +++ b/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); diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java index d9e25ea89..dd554113e 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/authz/oauth2/provider/token/DefaultTokenServices.java +++ b/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; + } + + } \ No newline at end of file diff --git a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/autoconfigure/Oauth20AutoConfiguration.java b/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/autoconfigure/Oauth20AutoConfiguration.java index 9ba02e155..cd2baa007 100644 --- a/maxkey-protocols/maxkey-protocol-oauth-2.0/src/main/java/org/dromara/maxkey/autoconfigure/Oauth20AutoConfiguration.java +++ b/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; } diff --git a/maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/contorller/LogoutEndpoint.java b/maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/contorller/LogoutEndpoint.java index 2b87d6a21..f86f904bd 100644 --- a/maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/contorller/LogoutEndpoint.java +++ b/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> entrySet = session.getAuthorizedApps().entrySet(); + Set> entrySet = session.getVisited().entrySet(); - Iterator> iterator = entrySet.iterator(); + Iterator> iterator = entrySet.iterator(); while (iterator.hasNext()) { - Entry mapEntry = iterator.next(); + Entry 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 diff --git a/maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/interceptor/SingleSignOnInterceptor.java b/maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/interceptor/SingleSignOnInterceptor.java index aa00ab2a4..5a4ee18cf 100644 --- a/maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/interceptor/SingleSignOnInterceptor.java +++ b/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); } }