SAML UPDATE

支持腾讯云和阿里云SAML 单点登录,支持属性扩展
上级 025912d1
......@@ -10,15 +10,23 @@ package org.maxkey.domain;
public class ExtraAttr {
String attr;
String type;
String value;
public ExtraAttr(String attr, String value) {
super();
this.attr = attr;
this.value = value;
}
/**
* @param attr
* @param value
*/
public ExtraAttr(String attr, String value) {
public ExtraAttr(String attr, String type,String value) {
super();
this.attr = attr;
this.type=type;
this.value = value;
}
public String getAttr() {
......@@ -34,6 +42,12 @@ public class ExtraAttr {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "ExtraAttr [attr=" + attr + ", value=" + value + "]";
......
......@@ -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
......
......@@ -46,6 +46,9 @@ public class SAML20DetailsController extends BaseAppContorller {
@Autowired
AppsSaml20DetailsService saml20DetailsService;
@Autowired
String maxKeyURI;
@RequestMapping(value = { "/forwardAdd" })
public ModelAndView forwardAdd() {
ModelAndView modelAndView=new ModelAndView("apps/saml20/appAdd");
......@@ -84,6 +87,7 @@ public class SAML20DetailsController extends BaseAppContorller {
decoderSecret(saml20Details);
WebContext.setAttribute(saml20Details.getId(), saml20Details.getIcon());
modelAndView.addObject("model",saml20Details);
modelAndView.addObject("maxKeyURI",maxKeyURI);
return modelAndView;
}
/**
......
......@@ -8,6 +8,7 @@ config.server.name=http://${config.server.domain.sub}
config.server.prefix.uri=${config.server.name}:9521/maxkey-mgt
#default.uri
config.server.default.uri=${config.server.prefix.uri}/main
config.maxkey.uri=${config.server.name}/maxkey
############################################################################
# Application Configuration
############################################################################
......
......@@ -321,6 +321,7 @@ apps.saml.nameIdConvert=NameId Convert
apps.saml.target=\u76EE\u6807\u5730\u5740
apps.saml.metadata.telephoneNumber=\u7535\u8BDD\u53F7\u7801
apps.saml.fileType.metadata=SAML\u5143\u6570\u636E
apps.saml.fileType.certificate=\u8BC1\u4E66
apps.saml.metadata.givenName=\u540D
apps.saml.issuer=Issuer
apps.saml.nameIdConvert.upperCase=\u5927\u5199
......
......@@ -319,6 +319,7 @@ apps.saml.nameIdConvert=NameId Convert
apps.saml.target=target
apps.saml.metadata.telephoneNumber=telephoneNumber
apps.saml.fileType.metadata=SAML Metadata Type
apps.saml.fileType.certificate=Certificate
apps.saml.metadata.givenName=givenName
apps.saml.issuer=Issuer
apps.saml.nameIdConvert.upperCase=upperCase
......
......@@ -53,6 +53,10 @@
<constructor-arg value="${config.saml.v20.sp.issuing.entity.id}"/>
</bean>
<bean id="maxKeyURI" class="java.lang.String" >
<constructor-arg value="${config.maxkey.uri}"/>
</bean>
<bean id="oauth20JdbcClientDetailsService" class="org.maxkey.authz.oauth2.provider.client.JdbcClientDetailsService">
<constructor-arg ref="dataSource" />
<property name="passwordEncoder" ref="passwordReciprocal"></property>
......
......@@ -32,15 +32,18 @@ $(function(){
var attrIndex = 0;
function addExtendAttr(attribute,attributeValue){
var html = '<tr id="extendTr_' + attrIndex + '"><th><@locale code="apps.formbased.parameter"/>:';
html += '<input class="button delExtendTr" type="button" name="delExtendTr" attrTrId="extendTr_'+attrIndex+'" value="<@locale code="button.text.delete" />"/>';
html += '</th><td>';
html += '<input type="text" class="form-control" id="attribute_' + attrIndex + '" name="attribute" class="int" title="" value="'+attribute+'"/>';
html += '</span></td><th><@locale code="apps.formbased.parameter.value"/>:</th> <td><span class="intspan">';
html += '<input type="text" class="form-control" id="attributeValue_' + attrIndex + '" name="attributeValue" class="int" title="" value="'+attributeValue+'"/>';
html += '</span>';
var html = '<tr id="extendTr_' + attrIndex + '">';
html += '<th><@locale code="apps.formbased.parameter"/>:';
html += '<input class="button delExtendTr" type="button" name="delExtendTr" attrTrId="extendTr_'+attrIndex+'" value="<@locale code="button.text.delete" />"/>';
html += '</th>';
html += '<td>';
html += '<input type="text" class="form-control" id="attribute_' + attrIndex + '" name="attribute" class="int" title="" value="'+attribute+'"/>';
html += '</span></td>';
html += '<th><@locale code="apps.formbased.parameter.value"/>:</th> <td><span class="intspan">';
html += '<input type="text" class="form-control" id="attributeValue_' + attrIndex + '" name="attributeValue" class="int" title="" value="'+attributeValue+'"/>';
html += '</span></td>';
html += '</td></tr>';
html += '</tr>';
$('#extendAttrBody').append(html);
attrIndex++;
}
......
......@@ -12,8 +12,7 @@
<script type="text/javascript">
<!--
$(function(){
$("#protocol_text").html("<%=PROTOCOLS.SAML20%>");
$("#protocol").val("<%=PROTOCOLS.SAML20%>");
});
//-->
</script>
......
......@@ -55,6 +55,8 @@ $(function(){
<td colspan =3>
<input type="text" class="form-control" id="entityId" name="entityId" title="" value="${model.entityId}"/>
</td>
</tr>
<tr>
<th><@locale code="apps.saml.spAcsUrl" /></th>
......@@ -70,9 +72,12 @@ $(function(){
</tr>
<tr>
<th><@locale code="apps.saml.audience" /></th>
<td colspan =3>
<td colspan =2>
<input type="text" class="form-control" id="audience" name="audience" title="" value="${model.audience}"/>
</td>
<td >
<a target="_blank" href="${maxKeyURI}/metadata/saml20/${model.id}.xml"> SAML MetaData</a>
</td>
</tr>
<tr>
<th style="width:15%;"><@locale code="apps.saml.nameidFormat" /></th>
......
<%@page contentType="text/xml; charset=UTF-8" %>${metadata}
\ No newline at end of file
......@@ -12,7 +12,7 @@
</head>
<body>
<form id="actionForm" method="post" type="label" autoclose="true" action="<@base/>/users/changePassword">
<form id="actionForm" method="post" type="label" autoclose="true" action="<@base/>/userinfo/changePassword">
<table class="table table-bordered" >
<tbody>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册