Crystal.Sea 4 年 前
コミット
49246f0ffa

+ 0 - 16
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/CasSingleLogout.java

@@ -1,16 +0,0 @@
-package org.maxkey.authz.singlelogout;
-
-public class CasSingleLogout extends SingleLogout{
-
-    public String logoutRequestMessage=
-            "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"%s\" Version=\"2.0\" "
-            + "IssueInstant=\"%s\"><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">%s"
-            + "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>";
-
-    @Override
-    public void sendRequest() {
-        // TODO Auto-generated method stub
-        
-    }
-    
-}

+ 16 - 7
maxkey-protocols/maxkey-protocol-authorize/src/main/java/org/maxkey/authz/singlelogout/DefaultSingleLogout.java

@@ -1,15 +1,24 @@
 package org.maxkey.authz.singlelogout;
 
-public class DefaultSingleLogout extends 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 String logoutRequestMessage=
-            "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"%s\" Version=\"2.0\" "
-            + "IssueInstant=\"%s\"><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">%s"
-            + "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>";
+public class DefaultSingleLogout extends SingleLogout{
 
     @Override
-    public void sendRequest() {
-        // TODO Auto-generated method stub
+    public void sendRequest(Authentication authentication,Apps logoutApp) {
+        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",  ((SigninPrincipal)authentication.getPrincipal()).getOnlineTicket().getTicketId());
+        postMessage(logoutApp.getLogoutUrl(),logoutParameters);
         
     }
     

+ 40 - 0
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=
+            "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"%s\" Version=\"2.0\" "
+            + "IssueInstant=\"%s\"><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">%s"
+            + "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>";
+
+    @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<String,Object> logoutParameters  = new HashMap<String,Object>();
+        logoutParameters.put(LOGOUT_REQUEST_PARAMETER, requestMessage);
+        postMessage(logoutApp.getLogoutUrl(),logoutParameters);
+    }
+
+    public SamlSingleLogout() {
+        super();
+    }
+    
+}

+ 96 - 2
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<String, Object> 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<NameValuePair> nvps = new ArrayList<NameValuePair>();
+            // 通过map集成entrySet方法获取entity
+            Set<Entry<String, Object>> entrySet = paramMap.entrySet();
+            // 循环遍历,获取迭代器
+            Iterator<Entry<String, Object>> iterator = entrySet.iterator();
+            while (iterator.hasNext()) {
+                Entry<String, Object> 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();
+                }
+            }
+        }
+    }
 }

+ 31 - 2
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<Entry<String, Apps>> entrySet = onlineTicket.getAuthorizedApps().entrySet();
+ 
+        Iterator<Entry<String, Apps>> iterator = entrySet.iterator();
+        while (iterator.hasNext()) {
+            Entry<String, Apps> 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();