SAML UPDATE
支持腾讯云和阿里云SAML 单点登录,支持属性扩展
This commit is contained in:
@@ -86,11 +86,11 @@ public class MetadataEndpoint {
|
||||
|
||||
IDPSSODescriptor descriptor = metadataGenerator.buildIDPSSODescriptor();
|
||||
|
||||
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authorize/"+appId,null));
|
||||
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,null));
|
||||
|
||||
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authorize/"+appId,SAMLConstants.SAML2_REDIRECT_BINDING_URI));
|
||||
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,SAMLConstants.SAML2_REDIRECT_BINDING_URI));
|
||||
|
||||
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authorize/"+appId,SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI));
|
||||
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI));
|
||||
|
||||
descriptor.getSingleLogoutServices().add(metadataGenerator.getSingleLogoutService(WebContext.getHttpContextPath()+"/logout",null));
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.maxkey.authn.BasicAuthentication;
|
||||
import org.maxkey.authz.saml.common.AuthnRequestInfo;
|
||||
import org.maxkey.authz.saml.common.EndpointGenerator;
|
||||
import org.maxkey.authz.saml20.binding.BindingAdapter;
|
||||
@@ -48,7 +49,7 @@ public class AssertionEndpoint {
|
||||
bindingAdapter = (BindingAdapter) request.getSession().getAttribute("samlv20Adapter");
|
||||
logger.debug("saml20 assertion get session samlv20Adapter "+bindingAdapter);
|
||||
AppsSAML20Details saml20Details = bindingAdapter.getSaml20Details();
|
||||
|
||||
logger.debug("saml20Details "+saml20Details.getExtendAttr());
|
||||
AuthnRequestInfo authnRequestInfo = bindingAdapter.getAuthnRequestInfo();
|
||||
|
||||
if (authnRequestInfo == null) {
|
||||
@@ -67,7 +68,10 @@ public class AssertionEndpoint {
|
||||
grantedAuthority.add(anthGrantedAuthority);
|
||||
}
|
||||
//TODO:
|
||||
String userName =authToken.getPrincipal().toString();
|
||||
//String userName ="shimingxy@qq.com";
|
||||
String userName =((BasicAuthentication )authToken.getPrincipal()).getJ_username();
|
||||
//aly
|
||||
//String userName ="admin@1729982683323703.onaliyun.com";
|
||||
DateTime authnInstant = new DateTime(request.getSession().getCreationTime());
|
||||
|
||||
String remoteAddress=WebContext.getRequestIpAddress(request);
|
||||
|
||||
@@ -75,7 +75,6 @@ public class AssertionGenerator {
|
||||
|
||||
AttributeStatement attributeStatement =attributeStatementGenerator.generateAttributeStatement(authorities, attributeMap);
|
||||
assertion.getAttributeStatements().add(attributeStatement);
|
||||
|
||||
assertion.setID(idService.generateID());
|
||||
assertion.setIssueInstant(timeService.getCurrentDateTime());
|
||||
|
||||
|
||||
@@ -5,6 +5,12 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.maxkey.authz.saml20.binding.BindingAdapter;
|
||||
import org.maxkey.domain.ExtraAttr;
|
||||
import org.maxkey.domain.ExtraAttrs;
|
||||
import org.maxkey.domain.apps.AppsSAML20Details;
|
||||
import org.maxkey.web.WebContext;
|
||||
import org.opensaml.Configuration;
|
||||
import org.opensaml.saml2.core.Attribute;
|
||||
import org.opensaml.saml2.core.AttributeStatement;
|
||||
@@ -14,10 +20,13 @@ import org.opensaml.saml2.core.impl.AttributeStatementBuilder;
|
||||
import org.opensaml.xml.XMLObjectBuilderFactory;
|
||||
import org.opensaml.xml.schema.XSString;
|
||||
import org.opensaml.xml.schema.impl.XSStringBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class AttributeStatementGenerator {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AttributeStatementGenerator.class);
|
||||
|
||||
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
|
||||
|
||||
public AttributeStatement generateAttributeStatement(Collection<GrantedAuthority> authorities) {
|
||||
@@ -44,22 +53,38 @@ public class AttributeStatementGenerator {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
|
||||
Attribute attribute=builderAttribute(key,value);
|
||||
Attribute attribute=builderAttribute(key,value,Attribute.BASIC);
|
||||
|
||||
attributeStatement.getAttributes().add(attribute);
|
||||
|
||||
}
|
||||
}
|
||||
BindingAdapter bindingAdapter = (BindingAdapter) WebContext.getSession().getAttribute("samlv20Adapter");
|
||||
AppsSAML20Details saml20Details = bindingAdapter.getSaml20Details();
|
||||
logger.debug("ExtendAttr "+saml20Details.getExtendAttr());
|
||||
ExtraAttrs extraAttrs=new ExtraAttrs(saml20Details.getExtendAttr());
|
||||
for(ExtraAttr extraAttr : extraAttrs.getExtraAttrs()) {
|
||||
logger.debug("Attribute : "+extraAttr.getAttr()+" , Vale : "+extraAttr.getValue()+" , Type : "+extraAttr.getType());
|
||||
attributeStatement.getAttributes().add(builderAttribute(extraAttr.getAttr(),extraAttr.getValue(),extraAttr.getType()));
|
||||
}
|
||||
//tencent
|
||||
//attributeStatement.getAttributes().add(builderAttribute("https://cloud.tencent.com/SAML/Attributes/Role","qcs::cam::uin/100013138092:roleName/cloud.tencent_maxkey,qcs::cam::uin/100013138092:saml-provider/maxkey",Attribute.UNSPECIFIED));
|
||||
//attributeStatement.getAttributes().add(builderAttribute("https://cloud.tencent.com/SAML/Attributes/RoleSessionName","maxkey",Attribute.UNSPECIFIED));
|
||||
//aliyun
|
||||
//attributeStatement.getAttributes().add(builderAttribute("https://www.aliyun.com/SAML-Role/Attributes/RoleSessionName","2037230828547234327",Attribute.UNSPECIFIED));
|
||||
//attributeStatement.getAttributes().add(builderAttribute("https://www.aliyun.com/SAML-Role/Attributes/Role","acs:ram::1729982683323703:role/maxkey,acs:ram::1729982683323703:saml-provider/maxkey",Attribute.UNSPECIFIED));
|
||||
//attributeStatement.getAttributes().add(builderAttribute("https://www.aliyun.com/SAML-Role/Attributes/SessionDuration","1800",Attribute.UNSPECIFIED));
|
||||
|
||||
return attributeStatement;
|
||||
}
|
||||
|
||||
public Attribute builderAttribute(String attributeName,String value ){
|
||||
public Attribute builderAttribute(String attributeName,String value ,String nameFormat){
|
||||
AttributeBuilder attributeBuilder = (AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
|
||||
Attribute attribute = attributeBuilder.buildObject();
|
||||
attribute.setName(attributeName);
|
||||
|
||||
// urn:oasis:names:tc:SAML:2.0:attrname-format:basic
|
||||
attribute.setNameFormat(Attribute.DEFAULT_ELEMENT_LOCAL_NAME);
|
||||
attribute.setNameFormat(nameFormat);
|
||||
|
||||
// Response/Assertion/AttributeStatement/Attribute/AttributeValue
|
||||
XSStringBuilder stringBuilder = (XSStringBuilder) builderFactory.getBuilder(XSString.TYPE_NAME);
|
||||
@@ -75,7 +100,7 @@ public class AttributeStatementGenerator {
|
||||
// Response/Assertion/AttributeStatement/Attribute
|
||||
AttributeBuilder attributeBuilder = (AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
|
||||
Attribute attribute = attributeBuilder.buildObject();
|
||||
attribute.setName(GrantedAuthority.class.getName());
|
||||
attribute.setName("GrantedAuthority");
|
||||
|
||||
// urn:oasis:names:tc:SAML:2.0:attrname-format:basic
|
||||
attribute.setNameFormat(Attribute.BASIC);
|
||||
|
||||
@@ -26,8 +26,18 @@ import org.opensaml.xml.encryption.EncryptionConstants;
|
||||
import org.opensaml.xml.encryption.EncryptionException;
|
||||
import org.opensaml.xml.encryption.EncryptionParameters;
|
||||
import org.opensaml.xml.encryption.KeyEncryptionParameters;
|
||||
import org.opensaml.xml.io.Marshaller;
|
||||
import org.opensaml.xml.io.MarshallerFactory;
|
||||
import org.opensaml.xml.io.MarshallingException;
|
||||
import org.opensaml.xml.security.BasicSecurityConfiguration;
|
||||
import org.opensaml.xml.security.credential.BasicCredential;
|
||||
import org.opensaml.xml.security.credential.Credential;
|
||||
import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
|
||||
import org.opensaml.xml.signature.Signature;
|
||||
import org.opensaml.xml.signature.SignatureConstants;
|
||||
import org.opensaml.xml.signature.SignatureException;
|
||||
import org.opensaml.xml.signature.Signer;
|
||||
import org.opensaml.xml.signature.impl.SignatureBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
@@ -87,6 +97,10 @@ public class AuthnResponseGenerator {
|
||||
authnInstant);
|
||||
|
||||
try{
|
||||
|
||||
logger.debug("authResponse.isSigned "+authResponse.isSigned());
|
||||
|
||||
//assertion.setSignature(newSignature);
|
||||
if(BOOLEAN.isTrue(saml20Details.getEncrypted())) {
|
||||
// Assume this contains a recipient's RSA public
|
||||
logger.info("begin to encrypt assertion");
|
||||
@@ -107,20 +121,48 @@ public class AuthnResponseGenerator {
|
||||
encrypter.setKeyPlacement(KeyPlacement.PEER);
|
||||
EncryptedAssertion encryptedAssertion = encrypter.encrypt(assertion);
|
||||
authResponse.getEncryptedAssertions().add(encryptedAssertion);
|
||||
} else {
|
||||
authResponse.getAssertions().add(assertion);
|
||||
}
|
||||
}
|
||||
|
||||
SignatureBuilder signatureBuilder = (SignatureBuilder) builderFactory.getBuilder(Signature.DEFAULT_ELEMENT_NAME);
|
||||
BasicCredential basicCredential = new BasicCredential();
|
||||
basicCredential.setPrivateKey(signingCredential.getPrivateKey());
|
||||
|
||||
Signature signature = signatureBuilder.buildObject();
|
||||
signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
|
||||
signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||
|
||||
signature.setSigningCredential(basicCredential);
|
||||
KeyInfoGeneratorFactory keyInfoGeneratorFactory = Configuration
|
||||
.getGlobalSecurityConfiguration()
|
||||
.getKeyInfoGeneratorManager().getDefaultManager()
|
||||
.getFactory(signingCredential);
|
||||
|
||||
signature.setKeyInfo(keyInfoGeneratorFactory.newInstance().generate(signingCredential));
|
||||
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
|
||||
config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
|
||||
assertion.setSignature(signature);
|
||||
|
||||
Configuration.getMarshallerFactory().getMarshaller(assertion).marshall(assertion);
|
||||
Signer.signObject(signature);
|
||||
|
||||
logger.debug("assertion.isSigned "+assertion.isSigned());;
|
||||
authResponse.getAssertions().add(assertion);
|
||||
|
||||
}
|
||||
catch (EncryptionException e) {
|
||||
logger.info("Unable to encrypt assertion .");
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
authResponse.setIssuer(responseIssuer);
|
||||
authResponse.setID(idService.generateID());
|
||||
authResponse.setIssueInstant(timeService.getCurrentDateTime());
|
||||
authResponse.setInResponseTo(inResponseTo);
|
||||
authResponse.getAssertions().add(assertion);
|
||||
//authResponse.getAssertions().add(assertion);
|
||||
authResponse.setDestination(assertionConsumerURL);
|
||||
authResponse.setStatus(statusGenerator.generateStatus(StatusCode.SUCCESS_URI));
|
||||
return authResponse;
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.maxkey.authz.saml20.provider.xml;
|
||||
|
||||
|
||||
import org.maxkey.authz.saml.service.TimeService;
|
||||
import org.opensaml.Configuration;
|
||||
import org.opensaml.saml2.core.NameID;
|
||||
import org.opensaml.saml2.core.NameIDType;
|
||||
import org.opensaml.saml2.core.Subject;
|
||||
@@ -13,11 +12,10 @@ import org.opensaml.saml2.core.impl.NameIDBuilder;
|
||||
import org.opensaml.saml2.core.impl.SubjectBuilder;
|
||||
import org.opensaml.saml2.core.impl.SubjectConfirmationBuilder;
|
||||
import org.opensaml.saml2.core.impl.SubjectConfirmationDataBuilder;
|
||||
import org.opensaml.xml.XMLObjectBuilderFactory;
|
||||
|
||||
public class SubjectGenerator {
|
||||
|
||||
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
|
||||
//private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
|
||||
private final TimeService timeService;
|
||||
|
||||
public SubjectGenerator(TimeService timeService) {
|
||||
@@ -47,31 +45,30 @@ public class SubjectGenerator {
|
||||
}
|
||||
|
||||
public NameID builderNameID(String value,String strSPNameQualifier){
|
||||
//Response/Assertion/Subject/NameID
|
||||
NameIDBuilder nameIDBuilder = (NameIDBuilder) builderFactory.getBuilder(NameID.DEFAULT_ELEMENT_NAME);
|
||||
NameID nameID = nameIDBuilder.buildObject();
|
||||
//Response/Assertion/Subject/NameID
|
||||
NameID nameID = new NameIDBuilder().buildObject();
|
||||
nameID.setValue(value);
|
||||
nameID.setFormat(NameIDType.PERSISTENT);
|
||||
nameID.setSPNameQualifier(strSPNameQualifier);
|
||||
//nameID.setFormat(NameIDType.PERSISTENT);
|
||||
nameID.setFormat(NameIDType.UNSPECIFIED);
|
||||
//nameID.setSPNameQualifier(strSPNameQualifier);
|
||||
|
||||
return nameID;
|
||||
}
|
||||
|
||||
public Subject builderSubject (NameID nameID){
|
||||
//Response/Assertion/Subject
|
||||
SubjectBuilder subjectBuilder = (SubjectBuilder)builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME);
|
||||
Subject subject = subjectBuilder.buildObject();
|
||||
Subject subject = new SubjectBuilder().buildObject();
|
||||
subject.setNameID(nameID);
|
||||
return subject;
|
||||
}
|
||||
|
||||
public SubjectConfirmation builderSubjectConfirmation(String recipient,String inResponseTo,int validInSeconds,String clientAddress){
|
||||
SubjectConfirmationBuilder subjectConfirmationBuilder = (SubjectConfirmationBuilder)builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
|
||||
SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
|
||||
//SubjectConfirmationBuilder subjectConfirmationBuilder = (SubjectConfirmationBuilder)builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
|
||||
SubjectConfirmation subjectConfirmation = new SubjectConfirmationBuilder().buildObject();
|
||||
subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER);
|
||||
|
||||
SubjectConfirmationDataBuilder subjectConfirmationDataBuilder = (SubjectConfirmationDataBuilder)builderFactory.getBuilder(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
|
||||
SubjectConfirmationData subjectConfirmationData = subjectConfirmationDataBuilder.buildObject();
|
||||
//SubjectConfirmationDataBuilder subjectConfirmationDataBuilder = (SubjectConfirmationDataBuilder)builderFactory.getBuilder(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
|
||||
SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationDataBuilder().buildObject();
|
||||
|
||||
subjectConfirmationData.setRecipient(recipient);
|
||||
//if idp-init not need inResponseTo
|
||||
|
||||
Reference in New Issue
Block a user