Ver código fonte

Logout optimize

MaxKey 3 anos atrás
pai
commit
27ccc425b7

+ 6 - 1
maxkey-protocols/maxkey-protocol-cas/src/main/java/org/maxkey/authz/cas/endpoint/CasAuthorizeEndpoint.java

@@ -26,6 +26,7 @@ import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authn.session.Session;
 import org.maxkey.authn.web.AuthorizationUtils;
 import org.maxkey.authz.cas.endpoint.ticket.CasConstants;
@@ -177,6 +178,10 @@ public class CasAuthorizeEndpoint  extends CasBaseAuthorizeEndpoint{
 			HttpServletRequest request,
 			HttpServletResponse response,
 			@RequestParam(value=CasConstants.PARAMETER.SERVICE,required=false) String casService){
-		return WebContext.redirect("/logout?reLoginUrl=" + casService);
+		StringBuffer logoutUrl = new StringBuffer("force/logout");
+		if(StringUtils.isNotBlank(casService)){
+			logoutUrl.append("?").append("redirect_uri=").append(casService);
+		}
+		return WebContext.forward(logoutUrl.toString());
 	}
 }

+ 7 - 5
maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/provider/endpoint/LogoutSamlEndpoint.java

@@ -20,6 +20,7 @@ package org.maxkey.authz.saml20.provider.endpoint;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authz.saml20.binding.ExtractBindingAdapter;
 import org.maxkey.authz.saml20.xml.SAML2ValidatorSuite;
 import org.maxkey.web.WebContext;
@@ -61,8 +62,8 @@ public class LogoutSamlEndpoint {
                 HttpServletResponse response)throws Exception {
              SAMLMessageContext messageContext;
              logger.debug("extract SAML Message .");
+             StringBuffer logoutUrl = new StringBuffer("force/logout");
              try {
-                 
                  messageContext = extractRedirectBindingAdapter.extractSAMLMessageContext(request);
                  logger.debug("validate SAML LogoutRequest .");
                  LogoutRequest logoutRequest = (LogoutRequest) messageContext.getInboundSAMLMessage();
@@ -72,8 +73,10 @@ public class LogoutSamlEndpoint {
                  logger.debug("LogoutRequest IssueInstant "+logoutRequest.getIssueInstant());
                  logger.debug("LogoutRequest Destination "+logoutRequest.getDestination());
                  logger.debug("LogoutRequest NameID "+logoutRequest.getNameID().getValue());
-                 return WebContext.redirect("/logout");
-                 
+                 //add Destination
+                 if(StringUtils.isNotBlank(logoutRequest.getDestination())) {
+                	 logoutUrl.append("?").append("redirect_uri=").append(logoutRequest.getDestination());
+                 }
              } catch (MessageDecodingException e1) {
                  logger.error("Exception decoding SAML MessageDecodingException", e1);
              } catch (SecurityException e1) {
@@ -81,8 +84,7 @@ public class LogoutSamlEndpoint {
              }catch (ValidationException ve) {
                  logger.warn("logoutRequest Message failed Validation", ve);
              }
-             
-             return WebContext.redirect("/login");
+             return WebContext.forward(logoutUrl.toString());
         }
        
 }

+ 8 - 7
maxkey-web-frontend/maxkey-web-app/src/app/layout/basic/widgets/user.component.ts

@@ -1,24 +1,24 @@
 /*
  * Copyright [2022] [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.
  */
- 
 
 import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
 import { Router } from '@angular/router';
 import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
 import { SettingsService, User } from '@delon/theme';
+import { environment } from '@env/environment';
 
 @Component({
   selector: 'header-user',
@@ -74,10 +74,11 @@ export class HeaderUserComponent {
     return this.settings.user;
   }
 
-  constructor(private settings: SettingsService, private router: Router, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {}
+  constructor(private settings: SettingsService, private router: Router, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) { }
 
   logout(): void {
-    this.tokenService.clear();
-    this.router.navigateByUrl(this.tokenService.login_url!);
+    //this.tokenService.clear();
+    //this.router.navigateByUrl(this.tokenService.login_url!);
+    window.location.href = `${environment.api.baseUrl}force/logout`;
   }
 }

+ 55 - 0
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/logout.component.ts

@@ -0,0 +1,55 @@
+/*
+ * Copyright [2022] [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.
+ */
+
+import { Inject, Optional, Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { ReuseTabService } from '@delon/abc/reuse-tab';
+import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
+import { SettingsService } from '@delon/theme';
+
+import { AuthnService } from '../../service/authn.service';
+import { SocialsProviderService } from '../../service/socials-provider.service';
+import { CONSTS } from '../../shared/consts';
+
+@Component({
+  selector: 'app-logout',
+  template: ``
+})
+export class LogoutComponent implements OnInit {
+  redirect_uri = '';
+
+  constructor(
+    private router: Router,
+    private settingsService: SettingsService,
+    private authnService: AuthnService,
+    @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService,
+    @Optional()
+    @Inject(ReuseTabService)
+    private reuseTabService: ReuseTabService,
+    private route: ActivatedRoute
+  ) { }
+
+  ngOnInit(): void {
+    this.redirect_uri = this.route.snapshot.params[CONSTS.REDIRECT_URI];
+    this.authnService.logout();
+    this.tokenService.clear();
+    if (this.redirect_uri == null || this.redirect_uri == '') {
+      this.router.navigateByUrl(this.tokenService.login_url!);
+    } else {
+      this.router.navigateByUrl(this.redirect_uri);
+    }
+  }
+}

+ 3 - 1
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/passport-routing.module.ts

@@ -23,6 +23,7 @@ import { ForgotComponent } from './forgot/forgot.component';
 import { JwtAuthComponent } from './jwt-auth.component';
 import { UserLockComponent } from './lock/lock.component';
 import { UserLoginComponent } from './login/login.component';
+import { LogoutComponent } from './logout.component';
 import { UserRegisterResultComponent } from './register-result/register-result.component';
 import { UserRegisterComponent } from './register/register.component';
 
@@ -61,7 +62,8 @@ const routes: Routes = [
   },
   // 单页不包裹Layout
   { path: 'passport/callback/:provider', component: CallbackComponent },
-  { path: 'passport/jwt/auth', component: JwtAuthComponent }
+  { path: 'passport/jwt/auth', component: JwtAuthComponent },
+  { path: 'passport/logout', component: LogoutComponent }
 ];
 
 @NgModule({

+ 6 - 0
maxkey-web-frontend/maxkey-web-app/src/app/service/authn.service.ts

@@ -61,6 +61,12 @@ export class AuthnService {
     return this.http.post('/login/signin?_allow_anonymous=true', authParam);
   }
 
+  //退出
+  logout() {
+    this.cookieService.delete(CONSTS.CONGRESS);
+    return this.http.get('/login/logout');
+  }
+
   congress(authParam: any) {
     return this.http.post('/login/congress?_allow_anonymous=true', authParam);
   }

+ 1 - 1
maxkey-web-frontend/maxkey-web-app/src/environments/environment.ts

@@ -27,7 +27,7 @@ export const environment = {
   production: false,
   useHash: true,
   api: {
-    baseUrl: 'http://sso.maxkey.top:9527/sign',
+    baseUrl: 'http://sso.maxkey.top:9527/sign/',
     refreshTokenEnabled: true,
     refreshTokenType: 're-request'
   },

+ 42 - 11
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/LogoutEndpoint.java

@@ -21,15 +21,21 @@ import java.util.Iterator;
 import java.util.Set;
 import java.util.Map.Entry;
 
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+import org.maxkey.authn.SignPrincipal;
 import org.maxkey.authn.annotation.CurrentUser;
 import org.maxkey.authn.session.Session;
 import org.maxkey.authn.session.SessionManager;
+import org.maxkey.authn.web.AuthorizationUtils;
 import org.maxkey.authz.singlelogout.SamlSingleLogout;
 import org.maxkey.authz.singlelogout.DefaultSingleLogout;
 import org.maxkey.authz.singlelogout.LogoutType;
 import org.maxkey.authz.singlelogout.SingleLogout;
 import org.maxkey.configuration.ApplicationConfig;
 import org.maxkey.constants.ConstsProtocols;
+import org.maxkey.entity.Message;
 import org.maxkey.entity.UserInfo;
 import org.maxkey.entity.apps.Apps;
 import org.maxkey.web.WebContext;
@@ -40,23 +46,31 @@ import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.web.servlet.ModelAndView;
 
 @Tag(name = "1-3-单点注销接口文档模块")
 @Controller
 public class LogoutEndpoint {
 	private static Logger _logger = LoggerFactory.getLogger(LogoutEndpoint.class);
 
+	@Autowired 
+    ApplicationConfig applicationConfig;
+	
 	@Autowired
-    protected SessionManager sessionManager;
-	@Autowired
-	ApplicationConfig applicationConfig;
-
-	@Operation(summary = "单点注销接口", description = "reLoginUrl跳转地址",method="GET")
+    SessionManager sessionManager;
+	
+	/**
+	 * for front end
+	 * @param currentUser
+	 * @return ResponseEntity
+	 */
+	@Operation(summary = "前端注销接口", description = "前端注销接口",method="GET")
 	@RequestMapping(value={"/logout"}, produces = {MediaType.APPLICATION_JSON_VALUE})
- 	public ModelAndView logout(@CurrentUser UserInfo currentUser){
+ 	public  ResponseEntity<?> logout(@CurrentUser UserInfo currentUser){
 		//if logined in have onlineTicket ,need remove or logout back
 		String sessionId = currentUser.getSessionId();
  		Session session = sessionManager.get(sessionId);
@@ -77,14 +91,31 @@ public class LogoutEndpoint {
 	                singleLogout.sendRequest(session.getAuthentication(), mapEntry.getValue());
 	            }
 	        }
-	        
+	        //terminate session
 	        sessionManager.terminate(
 	        		session.getId(), 
 	        		currentUser.getId(),
 	        		currentUser.getUsername());
  		}
-		StringBuffer loginUrl = new StringBuffer(applicationConfig.getServerName()).append(applicationConfig.getFrontendUri()).append("/#/passport/login");
-		return WebContext.redirect(loginUrl.toString());
-// 		return new Message<String>().buildResponse();
+ 		return new Message<String>().buildResponse();
+ 	}
+	
+	@Operation(summary = "单点注销接口", description = "redirect_uri跳转地址",method="GET")
+	@RequestMapping(value={"/force/logout"})
+ 	public ModelAndView forceLogout(
+ 				HttpServletRequest request,
+ 				@RequestParam(value = "redirect_uri",required = false) String redirect_uri
+ 				){
+		//invalidate http session
+		request.getSession().invalidate();
+		StringBuffer logoutUrl = new StringBuffer("");
+		logoutUrl.append(applicationConfig.getFrontendUri()).append("/#/passport/logout");
+		if(StringUtils.isNotBlank(redirect_uri)) {
+			logoutUrl.append("?")
+				.append("redirect_uri=").append(redirect_uri);
+		}
+		ModelAndView modelAndView=new ModelAndView("redirect");
+		modelAndView.addObject("redirect_uri", logoutUrl);
+		return modelAndView;
  	}
 }

+ 12 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/redirect.ftl

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html >
+<head>
+	<script type="text/javascript">
+	   window.top.location.href = "${redirect_uri}";
+	</script>
+</head>
+
+<body  style="display:none;">
+
+</body>
+</html>