You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
8.3 KiB
204 lines
8.3 KiB
package com.fr.plugin.xxxx.saml.xxxx.saml; |
|
|
|
import org.apache.jcp.xml.dsig.internal.dom.DOMTransform; |
|
import org.jdom.Element; |
|
import org.jdom.Namespace; |
|
import org.jdom.input.DOMBuilder; |
|
import org.jdom.output.XMLOutputter; |
|
import org.w3c.dom.Node; |
|
import org.xml.sax.SAXException; |
|
|
|
import javax.xml.XMLConstants; |
|
import javax.xml.crypto.MarshalException; |
|
import javax.xml.crypto.dsig.*; |
|
import javax.xml.crypto.dsig.dom.DOMSignContext; |
|
import javax.xml.crypto.dsig.keyinfo.KeyInfo; |
|
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; |
|
import javax.xml.crypto.dsig.keyinfo.X509Data; |
|
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; |
|
import javax.xml.parsers.DocumentBuilderFactory; |
|
import javax.xml.parsers.ParserConfigurationException; |
|
import java.io.ByteArrayInputStream; |
|
import java.io.IOException; |
|
import java.io.Serializable; |
|
import java.io.StringWriter; |
|
import java.security.InvalidAlgorithmParameterException; |
|
import java.security.KeyStore.PrivateKeyEntry; |
|
import java.security.NoSuchAlgorithmException; |
|
import java.security.PrivateKey; |
|
import java.security.Provider; |
|
import java.security.cert.X509Certificate; |
|
import java.text.ParseException; |
|
import java.text.SimpleDateFormat; |
|
import java.util.*; |
|
|
|
public class SAMLUtil { |
|
|
|
public static String toStanderTime(Date date) { |
|
SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd"); |
|
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); |
|
|
|
TimeZone zone = TimeZone.getTimeZone("GMT"); |
|
dayFormat.setTimeZone(zone); |
|
timeFormat.setTimeZone(zone); |
|
return dayFormat.format(date) + 'T' + timeFormat.format(date) + 'Z'; |
|
} |
|
|
|
public static Calendar toDate(String t) { |
|
String date = t.substring(0, t.indexOf("T")); |
|
String time = t.substring(t.indexOf("T") + 1, t.length() - 1); |
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); |
|
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); |
|
// Time in GMT |
|
TimeZone zone = TimeZone.getTimeZone("GMT"); |
|
dateFormat.setTimeZone(zone); |
|
timeFormat.setTimeZone(zone); |
|
try { |
|
Date dd = dateFormat.parse(date); |
|
Date tt = timeFormat.parse(time); |
|
long m = dd.getTime() + tt.getTime(); |
|
Calendar cal = Calendar.getInstance(); |
|
cal.setTimeInMillis(m); |
|
return cal; |
|
} catch (ParseException e) { |
|
throw new IllegalArgumentException("Invalid SAML time"); |
|
} |
|
} |
|
|
|
public static void addNamespace(Element root, Namespace namespace) { |
|
if (root == null) { |
|
return; |
|
} |
|
root.setNamespace(namespace); |
|
if (root.getChildren() == null) { |
|
return; |
|
} |
|
for (int index = 0; index < root.getChildren().size(); index++) { |
|
Element child = (Element) root.getChildren().get(index); |
|
addNamespace(child, namespace); |
|
} |
|
} |
|
|
|
public static void insertSignature(org.w3c.dom.Element element, |
|
PrivateKeyEntry privateKey, Node insertBefore) throws SAMLException { |
|
String digestAlgorithm = SAMLAlgorithmUtil.getDigestAlgorithmValue(SAMLAlgorithmUtil.DigestAlgorithmEnum.SHA1.getKey()); |
|
String signatureAlgorithm = SAMLAlgorithmUtil.getSignatureAlgorithmValue(SAMLAlgorithmUtil.SignatureAlgorithmEnum.RSA_SHA1.getKey()); |
|
signSignature(element, privateKey, insertBefore, digestAlgorithm, |
|
signatureAlgorithm); |
|
} |
|
|
|
public static void insertSignature(org.w3c.dom.Element element, |
|
PrivateKeyEntry privateKey, Node insertBefore, String digestAlgorithm,String signatureAlgorithm) |
|
throws SAMLException { |
|
signSignature(element, privateKey, insertBefore, |
|
digestAlgorithm,signatureAlgorithm); |
|
} |
|
|
|
|
|
private static void signSignature(org.w3c.dom.Element element, |
|
PrivateKeyEntry privateKey, Node insertBefore,String digestAlgorithm ,String signatureAlgorithm) throws SAMLException { |
|
String JSR_105_PROVIDER = "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI"; |
|
String providerName = System.getProperty("jsr105Provider", |
|
JSR_105_PROVIDER); |
|
try { |
|
Provider provider = (Provider) Class.forName(providerName).newInstance(); |
|
|
|
// 创建XML签名工厂 |
|
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM", provider); |
|
TransformService ts = TransformService.getInstance(Transform.ENVELOPED, "DOM", provider); |
|
DOMTransform domTrasform = new DOMTransform(ts); |
|
CanonicalizationMethod canMethod = factory.newCanonicalizationMethod( |
|
CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null); |
|
|
|
element.setIdAttribute("ID", true); |
|
String refId = element.getAttribute("ID"); |
|
|
|
//消息摘要包括:MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)、MAC(Message AuthenticationCode,消息认证码算法) |
|
//这里采用 安全散列算法SHA |
|
Reference ref = factory.newReference("#" + refId, |
|
factory.newDigestMethod(SAMLAlgorithmUtil.getDigestAlgorithmValue(digestAlgorithm), null), |
|
Collections.singletonList(domTrasform), null, null); |
|
|
|
// SignatureMethod signatureMethod = factory.newSignatureMethod( |
|
// SignatureMethod.RSA_SHA1, null); |
|
// 数字签名算法 MD5和SHA1分别是MD、SHA算法系列中最有代表性的算法 |
|
SignatureMethod signatureMethod = factory.newSignatureMethod( |
|
SAMLAlgorithmUtil.getSignatureAlgorithmValue(signatureAlgorithm), null); |
|
|
|
SignedInfo signedInfo = factory.newSignedInfo(canMethod, |
|
signatureMethod, Collections.singletonList(ref)); |
|
|
|
X509Certificate cert = (X509Certificate) privateKey.getCertificate(); |
|
KeyInfoFactory kif = factory.getKeyInfoFactory(); |
|
List<Serializable> x509Content = new ArrayList<Serializable>(); |
|
x509Content.add(cert); |
|
X509Data xd = kif.newX509Data(x509Content); |
|
KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(xd)); |
|
PrivateKey key = privateKey.getPrivateKey(); |
|
DOMSignContext dsc = new DOMSignContext(key, element); |
|
dsc.setNextSibling(insertBefore); |
|
XMLSignature signature = factory.newXMLSignature(signedInfo,keyInfo); |
|
signature.sign(dsc); |
|
} catch (IllegalAccessException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} catch (MarshalException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} catch (XMLSignatureException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} catch (InstantiationException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} catch (ClassNotFoundException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} catch (NoSuchAlgorithmException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} catch (InvalidAlgorithmParameterException e) { |
|
throw new SAMLException("Error insertSignature:" + e.getMessage(),e); |
|
} |
|
} |
|
|
|
public static org.w3c.dom.Document toDom(org.jdom.Document doc) |
|
throws SAMLException { |
|
try { |
|
XMLOutputter xmlOutputter = new XMLOutputter(); |
|
StringWriter elemStrWriter = new StringWriter(); |
|
xmlOutputter.output(doc, elemStrWriter); |
|
byte[] xmlBytes = elemStrWriter.toString().getBytes(); |
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
|
dbf.setNamespaceAware(true); |
|
setDocumentBuilderFeature(dbf); |
|
return dbf.newDocumentBuilder().parse( |
|
new ByteArrayInputStream(xmlBytes)); |
|
} catch (IOException e) { |
|
throw new SAMLException("Error JDOM to W3 DOM: " + e.getMessage(), e); |
|
} catch (ParserConfigurationException e) { |
|
throw new SAMLException("Error JDOM to W3 DOM: " + e.getMessage(), e); |
|
} catch (SAXException e) { |
|
throw new SAMLException("Error JDOM to W3 DOM: " + e.getMessage(), e); |
|
} |
|
} |
|
|
|
public static org.w3c.dom.Element toDom(org.jdom.Element element) |
|
throws SAMLException { |
|
org.jdom.Document doc = element.getDocument(); |
|
if (doc == null) { |
|
throw new SAMLException("Invalid JDOM element"); |
|
} |
|
return toDom(element.getDocument()).getDocumentElement(); |
|
} |
|
|
|
public static org.jdom.Element toJdom(org.w3c.dom.Element e) { |
|
DOMBuilder builder = new DOMBuilder(); |
|
org.jdom.Element jdomElem = builder.build(e); |
|
return jdomElem; |
|
} |
|
|
|
public static void setDocumentBuilderFeature(DocumentBuilderFactory dbf) |
|
throws ParserConfigurationException { |
|
//必选 |
|
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true ); |
|
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); |
|
//必选 |
|
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); |
|
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); |
|
} |
|
}
|
|
|