diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/CasSingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/CasSingleLogout.java
deleted file mode 100644
index 1451fae18..000000000
--- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/CasSingleLogout.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.maxkey.authz.singlelogout;
-
-public class CasSingleLogout extends SingleLogout{
-
- public String logoutRequestMessage=
- "%s"
- + "%s";
-
- @Override
- public void sendRequest() {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/DefaultSingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/DefaultSingleLogout.java
index 7ef581944..66101c81b 100644
--- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/DefaultSingleLogout.java
+++ b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/DefaultSingleLogout.java
@@ -1,15 +1,24 @@
package org.maxkey.authz.singlelogout;
+import java.util.HashMap;
+import java.util.UUID;
+
+import org.maxkey.authn.SigninPrincipal;
+import org.maxkey.domain.apps.Apps;
+import org.maxkey.util.DateUtils;
+import org.springframework.security.core.Authentication;
+
public class DefaultSingleLogout extends SingleLogout{
- public String logoutRequestMessage=
- "%s"
- + "%s";
-
@Override
- public void sendRequest() {
- // TODO Auto-generated method stub
+ public void sendRequest(Authentication authentication,Apps logoutApp) {
+ 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", ((SigninPrincipal)authentication.getPrincipal()).getOnlineTicket().getTicketId());
+ postMessage(logoutApp.getLogoutUrl(),logoutParameters);
}
diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java
new file mode 100644
index 000000000..3ef02284b
--- /dev/null
+++ b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SamlSingleLogout.java
@@ -0,0 +1,40 @@
+package org.maxkey.authz.singlelogout;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+import org.maxkey.domain.apps.Apps;
+import org.maxkey.util.DateUtils;
+import org.springframework.security.core.Authentication;
+
+public class SamlSingleLogout extends SingleLogout{
+
+ /**
+ * The parameter name that contains the logout request.
+ */
+ public static final String LOGOUT_REQUEST_PARAMETER = "logoutRequest";
+
+ public static final String logoutRequestMessage=
+ "%s"
+ + "%s";
+
+ @Override
+ public void sendRequest(Authentication authentication,Apps logoutApp) {
+ String requestMessage = String.format(logoutRequestMessage,
+ UUID.randomUUID().toString(),
+ DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_ISO_TIMESTAMP),
+ authentication.getName(),
+ logoutApp.getOnlineTicket()
+ );
+
+ HashMap logoutParameters = new HashMap();
+ logoutParameters.put(LOGOUT_REQUEST_PARAMETER, requestMessage);
+ postMessage(logoutApp.getLogoutUrl(),logoutParameters);
+ }
+
+ public SamlSingleLogout() {
+ super();
+ }
+
+}
diff --git a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SingleLogout.java b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SingleLogout.java
index ccb9e6be4..6557dafdf 100644
--- a/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SingleLogout.java
+++ b/maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/SingleLogout.java
@@ -1,7 +1,101 @@
package org.maxkey.authz.singlelogout;
-public abstract class SingleLogout {
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import org.apache.http.HttpEntity;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.maxkey.domain.apps.Apps;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+
+public abstract class SingleLogout {
+ private static final Logger _logger = LoggerFactory.getLogger(SingleLogout.class);
- public abstract void sendRequest() ;
+ public abstract void sendRequest(Authentication authentication,Apps logoutApp) ;
+
+ public void postMessage(String url,Map paramMap) {
+ // 创建httpClient实例
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ CloseableHttpResponse httpResponse = null;
+ // 创建httpPost远程连接实例
+ HttpPost httpPost = new HttpPost(url);
+ // 配置请求参数实例
+ RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 设置连接主机服务超时时间
+ .setConnectionRequestTimeout(35000)// 设置连接请求超时时间
+ .setSocketTimeout(60000)// 设置读取数据连接超时时间
+ .build();
+ // 为httpPost实例设置配置
+ httpPost.setConfig(requestConfig);
+ // 设置请求头
+ httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
+ // 封装post请求参数
+ if (null != paramMap && paramMap.size() > 0) {
+ List nvps = new ArrayList();
+ // 通过map集成entrySet方法获取entity
+ Set> entrySet = paramMap.entrySet();
+ // 循环遍历,获取迭代器
+ Iterator> iterator = entrySet.iterator();
+ while (iterator.hasNext()) {
+ Entry mapEntry = iterator.next();
+ _logger.debug("Name " + mapEntry.getKey() + " , Value " +mapEntry.getValue());
+ nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString()));
+ }
+
+ // 为httpPost设置封装好的请求参数
+ try {
+ httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ try {
+ _logger.debug("Post URL " + url + " , Post Message \n" +
+ httpPost.getEntity().toString()
+ );
+ // httpClient对象执行post请求,并返回响应参数对象
+ httpResponse = httpClient.execute(httpPost);
+ // 从响应对象中获取响应内容
+ HttpEntity entity = httpResponse.getEntity();
+ _logger.debug("Http Response StatusCode " +
+ httpResponse.getStatusLine().getStatusCode()+
+ " , Content " +EntityUtils.toString(entity)
+ );
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ // 关闭资源
+ if (null != httpResponse) {
+ try {
+ httpResponse.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (null != httpClient) {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
}
diff --git a/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LogoutEndpoint.java b/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LogoutEndpoint.java
index 1491b838c..2b1b867b5 100644
--- a/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LogoutEndpoint.java
+++ b/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LogoutEndpoint.java
@@ -17,13 +17,23 @@
package org.maxkey.web.endpoint;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Map.Entry;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
import org.maxkey.authn.SigninPrincipal;
+import org.maxkey.authn.online.OnlineTicket;
import org.maxkey.authn.online.OnlineTicketServices;
import org.maxkey.authn.realm.AbstractAuthenticationRealm;
+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.ConstantsProtocols;
+import org.maxkey.domain.apps.Apps;
import org.maxkey.web.WebConstants;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
@@ -95,7 +105,26 @@ public class LogoutEndpoint {
_logger.debug("re Login URL : "+ reLoginUrl);
modelAndView.addObject("reloginUrl",reLoginUrl);
- onlineTicketServices.remove(((SigninPrincipal)WebContext.getAuthentication().getPrincipal()).getOnlineTicket().getTicketId());
+ String onlineTicketId = ((SigninPrincipal)WebContext.getAuthentication().getPrincipal()).getOnlineTicket().getTicketId();
+ OnlineTicket onlineTicket = onlineTicketServices.get(onlineTicketId);
+
+ Set> entrySet = onlineTicket.getAuthorizedApps().entrySet();
+
+ Iterator> iterator = entrySet.iterator();
+ while (iterator.hasNext()) {
+ Entry mapEntry = iterator.next();
+ _logger.debug("App Id : "+ mapEntry.getKey()+ " , " +mapEntry.getValue());
+ if( mapEntry.getValue().getLogoutType() == LogoutType.BACK_CHANNEL){
+ SingleLogout singleLogout;
+ if(mapEntry.getValue().getProtocol().equalsIgnoreCase(ConstantsProtocols.CAS)) {
+ singleLogout =new SamlSingleLogout();
+ }else {
+ singleLogout = new DefaultSingleLogout();
+ }
+ singleLogout.sendRequest(onlineTicket.getAuthentication(), mapEntry.getValue());
+ }
+ }
+ onlineTicketServices.remove(onlineTicketId);
request.getSession().invalidate();
SecurityContextHolder.clearContext();