SAML20DetailsController.java 9.4 KB
Newer Older
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright [2020] [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.
 */
 

MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
18 19
package org.maxkey.web.apps.contorller;

MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
20 21 22 23
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
24 25 26 27
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;
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
28
import org.maxkey.authz.saml20.metadata.MetadataDescriptorUtil;
MaxKey单点登录官方's avatar
jks  
MaxKey单点登录官方 已提交
29
import org.maxkey.configuration.ApplicationConfig;
M
v 3.3.0  
MaxKey 已提交
30 31
import org.maxkey.constants.ConstsOperateMessage;
import org.maxkey.constants.ConstsProtocols;
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
32
import org.maxkey.crypto.ReciprocalUtils;
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
33 34 35
import org.maxkey.crypto.cert.X509CertUtils;
import org.maxkey.crypto.keystore.KeyStoreLoader;
import org.maxkey.crypto.keystore.KeyStoreUtil;
M
MaxKey 已提交
36
import org.maxkey.entity.apps.AppsSAML20Details;
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
37
import org.maxkey.persistence.service.AppsSaml20DetailsService;
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
38 39 40
import org.maxkey.web.WebContext;
import org.maxkey.web.message.Message;
import org.maxkey.web.message.MessageType;
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
41 42 43
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
44 45 46
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
47
import org.springframework.beans.factory.annotation.Qualifier;
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
48 49 50 51 52 53 54 55 56 57
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;


@Controller
@RequestMapping(value={"/apps/saml20"})
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
58
public class SAML20DetailsController   extends BaseAppContorller {
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
59 60
	final static Logger _logger = LoggerFactory.getLogger(SAML20DetailsController.class);
	
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
61 62 63 64
	@Autowired
	@Qualifier("keyStoreLoader")
	private KeyStoreLoader idpKeyStoreLoader;
	
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
65
	@Autowired
MaxKey单点登录官方's avatar
m-11/6  
MaxKey单点登录官方 已提交
66
	AppsSaml20DetailsService saml20DetailsService;
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
67
	
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
68
	@Autowired
MaxKey单点登录官方's avatar
jks  
MaxKey单点登录官方 已提交
69
	ApplicationConfig applicationConfig;
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
70
	
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
71 72 73
	@RequestMapping(value = { "/forwardAdd" })
	public ModelAndView forwardAdd() {
		ModelAndView modelAndView=new ModelAndView("apps/saml20/appAdd");
MaxKey单点登录官方's avatar
m-11/6  
MaxKey单点登录官方 已提交
74
		AppsSAML20Details saml20Details=new AppsSAML20Details();
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
75
		saml20Details.setSecret(ReciprocalUtils.generateKey(""));
M
v 3.3.0  
MaxKey 已提交
76
		saml20Details.setProtocol(ConstsProtocols.SAML20);
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
77
		saml20Details.setId(saml20Details.generateId());
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
78 79 80 81 82 83 84
		modelAndView.addObject("model",saml20Details);
		 
		return modelAndView;
	}
	
	
	@RequestMapping(value={"/add"})
MaxKey单点登录官方's avatar
m-11/6  
MaxKey单点登录官方 已提交
85
	public ModelAndView insert(@ModelAttribute("saml20Details") AppsSAML20Details saml20Details) {
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
86 87 88 89 90 91 92
		_logger.debug("-Add  :" + saml20Details);

		try {
			transform(saml20Details);
		} catch (Exception e) {
			e.printStackTrace();
		}
M
MaxKey 已提交
93
		saml20Details.setInstId(WebContext.getUserInfo().getInstId());
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
94
		saml20DetailsService.insert(saml20Details);
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
95
		if (appsService.insertApp(saml20Details)) {
M
v 3.3.0  
MaxKey 已提交
96
			  new Message(WebContext.getI18nValue(ConstsOperateMessage.INSERT_SUCCESS),MessageType.success);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
97 98
			
		} else {
M
v 3.3.0  
MaxKey 已提交
99
			  new Message(WebContext.getI18nValue(ConstsOperateMessage.INSERT_SUCCESS),MessageType.error);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
100 101 102 103 104 105 106
		}
		return   WebContext.forward("forwardUpdate/"+saml20Details.getId());
	}
	
	@RequestMapping(value = { "/forwardUpdate/{id}" })
	public ModelAndView forwardUpdate(@PathVariable("id") String id) {
		ModelAndView modelAndView=new ModelAndView("apps/saml20/appUpdate");
M
MaxKey 已提交
107
		AppsSAML20Details saml20Details=saml20DetailsService.getAppDetails(id , false);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
108
		decoderSecret(saml20Details);
M
MaxKey 已提交
109
		saml20Details.transIconBase64();
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
110
		modelAndView.addObject("model",saml20Details);
111
		modelAndView.addObject("authzURI",applicationConfig.getAuthzUri());
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
112 113 114 115 116 117 118 119
		return modelAndView;
	}
	/**
	 * modify
	 * @param application
	 * @return
	 */
	@RequestMapping(value={"/update"})  
MaxKey单点登录官方's avatar
m-11/6  
MaxKey单点登录官方 已提交
120
	public ModelAndView update(@ModelAttribute("saml20Details") AppsSAML20Details saml20Details) {
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
121 122 123 124 125 126 127 128
		//
		_logger.debug("-update  application :" + saml20Details);
	   _logger.debug("");
		try {
			transform(saml20Details);
		} catch (Exception e) {
			e.printStackTrace();
		}
M
MaxKey 已提交
129
		saml20Details.setInstId(WebContext.getUserInfo().getInstId());
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
130
		saml20DetailsService.update(saml20Details);
MaxKey单点登录官方's avatar
MaxKey单点登录官方 已提交
131
		if (appsService.updateApp(saml20Details)) {
M
v 3.3.0  
MaxKey 已提交
132
			 new Message(WebContext.getI18nValue(ConstsOperateMessage.UPDATE_SUCCESS),MessageType.success);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
133 134
			
		} else {
M
v 3.3.0  
MaxKey 已提交
135
			 new Message(WebContext.getI18nValue(ConstsOperateMessage.UPDATE_ERROR),MessageType.error);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
136 137 138 139 140 141 142 143 144
		}
		return   WebContext.forward("forwardUpdate/"+saml20Details.getId());
	}
	

	@ResponseBody
	@RequestMapping(value={"/delete/{id}"})
	public Message delete(@PathVariable("id") String id) {
		_logger.debug("-delete  application :" + id);
MaxKey单点登录官方's avatar
m-11/6  
MaxKey单点登录官方 已提交
145
		if (saml20DetailsService.remove(id)&&appsService.remove(id)) {
M
v 3.3.0  
MaxKey 已提交
146
			return  new Message(WebContext.getI18nValue(ConstsOperateMessage.DELETE_SUCCESS),MessageType.success);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
147 148
			
		} else {
M
v 3.3.0  
MaxKey 已提交
149
			return  new Message(WebContext.getI18nValue(ConstsOperateMessage.DELETE_SUCCESS),MessageType.error);
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
150 151 152
		}
	}
	
MaxKey单点登录官方's avatar
m-11/6  
MaxKey单点登录官方 已提交
153
	protected AppsSAML20Details transform(AppsSAML20Details samlDetails) throws Exception{
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
154 155 156
		
		super.transform(samlDetails);
		
157 158 159 160 161 162
		if(null==samlDetails.getFileType()||samlDetails.getFileType().equals("certificate")){//certificate file
			try {
			    if (null!=samlDetails.getMetaFile()&&!samlDetails.getMetaFile().isEmpty()) {
					InputStream isCert = samlDetails.getMetaFile().getInputStream();
					X509Certificate trustCert = X509CertUtils.loadCertFromInputStream(isCert);
					samlDetails.setTrustCert(trustCert);
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
163
					isCert.close();
164 165 166 167
			    }
			} catch (IOException e) {
				_logger.error("read certificate file error .", e);
				throw new Exception("read certificate file error", e);
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
168
			}
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
		}else if(samlDetails.getFileType().equals("metadata_file")){//metadata file
		    if (null!=samlDetails.getMetaFile()&&!samlDetails.getMetaFile().isEmpty()) {
		        samlDetails = resolveMetaData(samlDetails,samlDetails.getMetaFile().getInputStream());
		    }
		}else if(samlDetails.getFileType().equals("metadata_url")){//metadata url
		    CloseableHttpClient httpClient = HttpClients.createDefault();
		    HttpPost post = new HttpPost(samlDetails.getMetaUrl());
            CloseableHttpResponse response = httpClient.execute(post);
            samlDetails = resolveMetaData(samlDetails,response.getEntity().getContent());;
            response.close();
            httpClient.close();
		}
		
		if(samlDetails.getTrustCert()!=null) {
    		samlDetails.setCertSubject(samlDetails.getTrustCert().getSubjectDN().getName());
    		samlDetails.setCertExpiration(samlDetails.getTrustCert().getNotAfter().toString());
    
MaxKey单点登录官方's avatar
v3.0.0  
MaxKey单点登录官方 已提交
186
    		samlDetails.setCertIssuer(X509CertUtils.getCommonName(samlDetails.getTrustCert().getIssuerX500Principal()));
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    		
    		KeyStore keyStore = KeyStoreUtil.clone(idpKeyStoreLoader.getKeyStore(),idpKeyStoreLoader.getKeystorePassword());
    
    		KeyStore trustKeyStore = null;
    		if (!samlDetails.getEntityId().equals("")) {
    			trustKeyStore = KeyStoreUtil.importTrustCertificate(keyStore,samlDetails.getTrustCert(), samlDetails.getEntityId());
    		} else {
    			trustKeyStore = KeyStoreUtil.importTrustCertificate(keyStore,samlDetails.getTrustCert());
    		}
    
    		byte[] keyStoreByte = KeyStoreUtil.keyStore2Bytes(trustKeyStore,idpKeyStoreLoader.getKeystorePassword());
    
    		// store KeyStore content
    		samlDetails.setKeyStore(keyStoreByte);
		}
MaxKey单点登录官方's avatar
a  
MaxKey单点登录官方 已提交
202 203 204
		
		return samlDetails;
	}
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
205
	
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	public AppsSAML20Details resolveMetaData(AppsSAML20Details samlDetails,InputStream inputStream) throws Exception {
	    X509Certificate trustCert = null;
	    EntityDescriptor entityDescriptor;
        try {
            entityDescriptor = MetadataDescriptorUtil.getInstance().getEntityDescriptor(inputStream);
        } catch (IOException e) {
            _logger.error("metadata  file resolve error .", e);
            throw new Exception("metadata  file resolve error", e);
        }
        SPSSODescriptor sPSSODescriptor = entityDescriptor.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
        String b64Encoder = sPSSODescriptor.getKeyDescriptors().get(0).getKeyInfo().getX509Datas().get(0).getX509Certificates().get(0).getValue();

        trustCert = X509CertUtils.loadCertFromB64Encoded(b64Encoder);
        
        samlDetails.setTrustCert(trustCert);
        samlDetails.setSpAcsUrl(sPSSODescriptor.getAssertionConsumerServices().get(0).getLocation());
        samlDetails.setEntityId(entityDescriptor.getEntityID());
        
        if(samlDetails.getIssuer()==null || samlDetails.getIssuer().equals("")) {
            samlDetails.setIssuer(entityDescriptor.getEntityID());
        }
        
        if(samlDetails.getAudience()==null || samlDetails.getAudience().equals("")) {
            samlDetails.setAudience(entityDescriptor.getEntityID());
        }

        _logger.info("SPSSODescriptor EntityID "+ entityDescriptor.getEntityID());
        return samlDetails;
	}
MaxKey单点登录官方's avatar
init  
MaxKey单点登录官方 已提交
235 236
	
}