Skip to content

Commit 6d10df3

Browse files
author
shimingxy
committed
SAML UPDATE
支持腾讯云和阿里云SAML 单点登录,支持属性扩展
1 parent 025912d commit 6d10df3

File tree

20 files changed

+144
-46
lines changed

20 files changed

+144
-46
lines changed

maxkey-core/src/main/java/org/maxkey/domain/ExtraAttr.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,23 @@
1010
public class ExtraAttr {
1111

1212
String attr;
13+
String type;
1314
String value;
1415

16+
public ExtraAttr(String attr, String value) {
17+
super();
18+
this.attr = attr;
19+
this.value = value;
20+
}
21+
1522
/**
1623
* @param attr
1724
* @param value
1825
*/
19-
public ExtraAttr(String attr, String value) {
26+
public ExtraAttr(String attr, String type,String value) {
2027
super();
2128
this.attr = attr;
29+
this.type=type;
2230
this.value = value;
2331
}
2432
public String getAttr() {
@@ -34,6 +42,12 @@ public void setValue(String value) {
3442
this.value = value;
3543
}
3644

45+
public String getType() {
46+
return type;
47+
}
48+
public void setType(String type) {
49+
this.type = type;
50+
}
3751
@Override
3852
public String toString() {
3953
return "ExtraAttr [attr=" + attr + ", value=" + value + "]";

maxkey-protocols/maxkey-protocol-saml-2.0/.sts4-cache/classpath-data.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/metadata/endpoint/MetadataEndpoint.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ public ModelAndView metadata(HttpServletRequest request,
8686

8787
IDPSSODescriptor descriptor = metadataGenerator.buildIDPSSODescriptor();
8888

89-
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authorize/"+appId,null));
89+
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,null));
9090

91-
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authorize/"+appId,SAMLConstants.SAML2_REDIRECT_BINDING_URI));
91+
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,SAMLConstants.SAML2_REDIRECT_BINDING_URI));
9292

93-
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authorize/"+appId,SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI));
93+
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI));
9494

9595
descriptor.getSingleLogoutServices().add(metadataGenerator.getSingleLogoutService(WebContext.getHttpContextPath()+"/logout",null));
9696

maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/provider/endpoint/AssertionEndpoint.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import javax.servlet.http.HttpServletResponse;
88

99
import org.joda.time.DateTime;
10+
import org.maxkey.authn.BasicAuthentication;
1011
import org.maxkey.authz.saml.common.AuthnRequestInfo;
1112
import org.maxkey.authz.saml.common.EndpointGenerator;
1213
import org.maxkey.authz.saml20.binding.BindingAdapter;
@@ -48,7 +49,7 @@ public ModelAndView assertion(HttpServletRequest request,HttpServletResponse res
4849
bindingAdapter = (BindingAdapter) request.getSession().getAttribute("samlv20Adapter");
4950
logger.debug("saml20 assertion get session samlv20Adapter "+bindingAdapter);
5051
AppsSAML20Details saml20Details = bindingAdapter.getSaml20Details();
51-
52+
logger.debug("saml20Details "+saml20Details.getExtendAttr());
5253
AuthnRequestInfo authnRequestInfo = bindingAdapter.getAuthnRequestInfo();
5354

5455
if (authnRequestInfo == null) {
@@ -67,7 +68,10 @@ public ModelAndView assertion(HttpServletRequest request,HttpServletResponse res
6768
grantedAuthority.add(anthGrantedAuthority);
6869
}
6970
//TODO:
70-
String userName =authToken.getPrincipal().toString();
71+
//String userName ="shimingxy@qq.com";
72+
String userName =((BasicAuthentication )authToken.getPrincipal()).getJ_username();
73+
//aly
74+
//String userName ="admin@1729982683323703.onaliyun.com";
7175
DateTime authnInstant = new DateTime(request.getSession().getCreationTime());
7276

7377
String remoteAddress=WebContext.getRequestIpAddress(request);

maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/provider/xml/AssertionGenerator.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ public Assertion generateAssertion(
7575

7676
AttributeStatement attributeStatement =attributeStatementGenerator.generateAttributeStatement(authorities, attributeMap);
7777
assertion.getAttributeStatements().add(attributeStatement);
78-
7978
assertion.setID(idService.generateID());
8079
assertion.setIssueInstant(timeService.getCurrentDateTime());
8180

maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/provider/xml/AttributeStatementGenerator.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
import java.util.Iterator;
66
import java.util.Map;
77
import java.util.Map.Entry;
8+
9+
import org.maxkey.authz.saml20.binding.BindingAdapter;
10+
import org.maxkey.domain.ExtraAttr;
11+
import org.maxkey.domain.ExtraAttrs;
12+
import org.maxkey.domain.apps.AppsSAML20Details;
13+
import org.maxkey.web.WebContext;
814
import org.opensaml.Configuration;
915
import org.opensaml.saml2.core.Attribute;
1016
import org.opensaml.saml2.core.AttributeStatement;
@@ -14,10 +20,13 @@
1420
import org.opensaml.xml.XMLObjectBuilderFactory;
1521
import org.opensaml.xml.schema.XSString;
1622
import org.opensaml.xml.schema.impl.XSStringBuilder;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
1725
import org.springframework.security.core.GrantedAuthority;
1826

1927
public class AttributeStatementGenerator {
20-
28+
private final static Logger logger = LoggerFactory.getLogger(AttributeStatementGenerator.class);
29+
2130
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
2231

2332
public AttributeStatement generateAttributeStatement(Collection<GrantedAuthority> authorities) {
@@ -44,22 +53,38 @@ public AttributeStatement generateAttributeStatement(
4453
String key = entry.getKey();
4554
String value = entry.getValue();
4655

47-
Attribute attribute=builderAttribute(key,value);
56+
Attribute attribute=builderAttribute(key,value,Attribute.BASIC);
4857

4958
attributeStatement.getAttributes().add(attribute);
5059

5160
}
5261
}
62+
BindingAdapter bindingAdapter = (BindingAdapter) WebContext.getSession().getAttribute("samlv20Adapter");
63+
AppsSAML20Details saml20Details = bindingAdapter.getSaml20Details();
64+
logger.debug("ExtendAttr "+saml20Details.getExtendAttr());
65+
ExtraAttrs extraAttrs=new ExtraAttrs(saml20Details.getExtendAttr());
66+
for(ExtraAttr extraAttr : extraAttrs.getExtraAttrs()) {
67+
logger.debug("Attribute : "+extraAttr.getAttr()+" , Vale : "+extraAttr.getValue()+" , Type : "+extraAttr.getType());
68+
attributeStatement.getAttributes().add(builderAttribute(extraAttr.getAttr(),extraAttr.getValue(),extraAttr.getType()));
69+
}
70+
//tencent
71+
//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));
72+
//attributeStatement.getAttributes().add(builderAttribute("https://cloud.tencent.com/SAML/Attributes/RoleSessionName","maxkey",Attribute.UNSPECIFIED));
73+
//aliyun
74+
//attributeStatement.getAttributes().add(builderAttribute("https://www.aliyun.com/SAML-Role/Attributes/RoleSessionName","2037230828547234327",Attribute.UNSPECIFIED));
75+
//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));
76+
//attributeStatement.getAttributes().add(builderAttribute("https://www.aliyun.com/SAML-Role/Attributes/SessionDuration","1800",Attribute.UNSPECIFIED));
77+
5378
return attributeStatement;
5479
}
5580

56-
public Attribute builderAttribute(String attributeName,String value ){
81+
public Attribute builderAttribute(String attributeName,String value ,String nameFormat){
5782
AttributeBuilder attributeBuilder = (AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
5883
Attribute attribute = attributeBuilder.buildObject();
5984
attribute.setName(attributeName);
6085

6186
// urn:oasis:names:tc:SAML:2.0:attrname-format:basic
62-
attribute.setNameFormat(Attribute.DEFAULT_ELEMENT_LOCAL_NAME);
87+
attribute.setNameFormat(nameFormat);
6388

6489
// Response/Assertion/AttributeStatement/Attribute/AttributeValue
6590
XSStringBuilder stringBuilder = (XSStringBuilder) builderFactory.getBuilder(XSString.TYPE_NAME);
@@ -75,7 +100,7 @@ public Attribute builderGrantedAuthority(Collection<GrantedAuthority> authorit
75100
// Response/Assertion/AttributeStatement/Attribute
76101
AttributeBuilder attributeBuilder = (AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
77102
Attribute attribute = attributeBuilder.buildObject();
78-
attribute.setName(GrantedAuthority.class.getName());
103+
attribute.setName("GrantedAuthority");
79104

80105
// urn:oasis:names:tc:SAML:2.0:attrname-format:basic
81106
attribute.setNameFormat(Attribute.BASIC);

maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/provider/xml/AuthnResponseGenerator.java

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,18 @@
2626
import org.opensaml.xml.encryption.EncryptionException;
2727
import org.opensaml.xml.encryption.EncryptionParameters;
2828
import org.opensaml.xml.encryption.KeyEncryptionParameters;
29+
import org.opensaml.xml.io.Marshaller;
30+
import org.opensaml.xml.io.MarshallerFactory;
31+
import org.opensaml.xml.io.MarshallingException;
32+
import org.opensaml.xml.security.BasicSecurityConfiguration;
33+
import org.opensaml.xml.security.credential.BasicCredential;
2934
import org.opensaml.xml.security.credential.Credential;
3035
import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
36+
import org.opensaml.xml.signature.Signature;
37+
import org.opensaml.xml.signature.SignatureConstants;
38+
import org.opensaml.xml.signature.SignatureException;
39+
import org.opensaml.xml.signature.Signer;
40+
import org.opensaml.xml.signature.impl.SignatureBuilder;
3141
import org.slf4j.Logger;
3242
import org.slf4j.LoggerFactory;
3343
import org.springframework.security.core.GrantedAuthority;
@@ -87,6 +97,10 @@ public Response generateAuthnResponse( AppsSAML20Details saml20Details,
8797
authnInstant);
8898

8999
try{
100+
101+
logger.debug("authResponse.isSigned "+authResponse.isSigned());
102+
103+
//assertion.setSignature(newSignature);
90104
if(BOOLEAN.isTrue(saml20Details.getEncrypted())) {
91105
// Assume this contains a recipient's RSA public
92106
logger.info("begin to encrypt assertion");
@@ -107,20 +121,48 @@ public Response generateAuthnResponse( AppsSAML20Details saml20Details,
107121
encrypter.setKeyPlacement(KeyPlacement.PEER);
108122
EncryptedAssertion encryptedAssertion = encrypter.encrypt(assertion);
109123
authResponse.getEncryptedAssertions().add(encryptedAssertion);
110-
} else {
111-
authResponse.getAssertions().add(assertion);
112-
}
124+
}
125+
126+
SignatureBuilder signatureBuilder = (SignatureBuilder) builderFactory.getBuilder(Signature.DEFAULT_ELEMENT_NAME);
127+
BasicCredential basicCredential = new BasicCredential();
128+
basicCredential.setPrivateKey(signingCredential.getPrivateKey());
129+
130+
Signature signature = signatureBuilder.buildObject();
131+
signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
132+
signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
133+
134+
signature.setSigningCredential(basicCredential);
135+
KeyInfoGeneratorFactory keyInfoGeneratorFactory = Configuration
136+
.getGlobalSecurityConfiguration()
137+
.getKeyInfoGeneratorManager().getDefaultManager()
138+
.getFactory(signingCredential);
139+
140+
signature.setKeyInfo(keyInfoGeneratorFactory.newInstance().generate(signingCredential));
141+
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
142+
config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
143+
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
144+
assertion.setSignature(signature);
145+
146+
Configuration.getMarshallerFactory().getMarshaller(assertion).marshall(assertion);
147+
Signer.signObject(signature);
148+
149+
logger.debug("assertion.isSigned "+assertion.isSigned());;
150+
authResponse.getAssertions().add(assertion);
151+
113152
}
114153
catch (EncryptionException e) {
115154
logger.info("Unable to encrypt assertion .");
116155
e.printStackTrace();
156+
} catch (Exception e) {
157+
// TODO Auto-generated catch block
158+
e.printStackTrace();
117159
}
118160

119161
authResponse.setIssuer(responseIssuer);
120162
authResponse.setID(idService.generateID());
121163
authResponse.setIssueInstant(timeService.getCurrentDateTime());
122164
authResponse.setInResponseTo(inResponseTo);
123-
authResponse.getAssertions().add(assertion);
165+
//authResponse.getAssertions().add(assertion);
124166
authResponse.setDestination(assertionConsumerURL);
125167
authResponse.setStatus(statusGenerator.generateStatus(StatusCode.SUCCESS_URI));
126168
return authResponse;

maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/maxkey/authz/saml20/provider/xml/SubjectGenerator.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44

55
import org.maxkey.authz.saml.service.TimeService;
6-
import org.opensaml.Configuration;
76
import org.opensaml.saml2.core.NameID;
87
import org.opensaml.saml2.core.NameIDType;
98
import org.opensaml.saml2.core.Subject;
@@ -13,11 +12,10 @@
1312
import org.opensaml.saml2.core.impl.SubjectBuilder;
1413
import org.opensaml.saml2.core.impl.SubjectConfirmationBuilder;
1514
import org.opensaml.saml2.core.impl.SubjectConfirmationDataBuilder;
16-
import org.opensaml.xml.XMLObjectBuilderFactory;
1715

1816
public class SubjectGenerator {
1917

20-
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
18+
//private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
2119
private final TimeService timeService;
2220

2321
public SubjectGenerator(TimeService timeService) {
@@ -47,31 +45,30 @@ public Subject generateSubject(
4745
}
4846

4947
public NameID builderNameID(String value,String strSPNameQualifier){
50-
//Response/Assertion/Subject/NameID
51-
NameIDBuilder nameIDBuilder = (NameIDBuilder) builderFactory.getBuilder(NameID.DEFAULT_ELEMENT_NAME);
52-
NameID nameID = nameIDBuilder.buildObject();
48+
//Response/Assertion/Subject/NameID
49+
NameID nameID = new NameIDBuilder().buildObject();
5350
nameID.setValue(value);
54-
nameID.setFormat(NameIDType.PERSISTENT);
55-
nameID.setSPNameQualifier(strSPNameQualifier);
51+
//nameID.setFormat(NameIDType.PERSISTENT);
52+
nameID.setFormat(NameIDType.UNSPECIFIED);
53+
//nameID.setSPNameQualifier(strSPNameQualifier);
5654

5755
return nameID;
5856
}
5957

6058
public Subject builderSubject (NameID nameID){
6159
//Response/Assertion/Subject
62-
SubjectBuilder subjectBuilder = (SubjectBuilder)builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME);
63-
Subject subject = subjectBuilder.buildObject();
60+
Subject subject = new SubjectBuilder().buildObject();
6461
subject.setNameID(nameID);
6562
return subject;
6663
}
6764

6865
public SubjectConfirmation builderSubjectConfirmation(String recipient,String inResponseTo,int validInSeconds,String clientAddress){
69-
SubjectConfirmationBuilder subjectConfirmationBuilder = (SubjectConfirmationBuilder)builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
70-
SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
66+
//SubjectConfirmationBuilder subjectConfirmationBuilder = (SubjectConfirmationBuilder)builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
67+
SubjectConfirmation subjectConfirmation = new SubjectConfirmationBuilder().buildObject();
7168
subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER);
7269

73-
SubjectConfirmationDataBuilder subjectConfirmationDataBuilder = (SubjectConfirmationDataBuilder)builderFactory.getBuilder(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
74-
SubjectConfirmationData subjectConfirmationData = subjectConfirmationDataBuilder.buildObject();
70+
//SubjectConfirmationDataBuilder subjectConfirmationDataBuilder = (SubjectConfirmationDataBuilder)builderFactory.getBuilder(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
71+
SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationDataBuilder().buildObject();
7572

7673
subjectConfirmationData.setRecipient(recipient);
7774
//if idp-init not need inResponseTo

maxkey-web-manage/.sts4-cache/classpath-data.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

maxkey-web-manage/src/main/java/org/maxkey/web/apps/contorller/SAML20DetailsController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public class SAML20DetailsController extends BaseAppContorller {
4646
@Autowired
4747
AppsSaml20DetailsService saml20DetailsService;
4848

49+
@Autowired
50+
String maxKeyURI;
51+
4952
@RequestMapping(value = { "/forwardAdd" })
5053
public ModelAndView forwardAdd() {
5154
ModelAndView modelAndView=new ModelAndView("apps/saml20/appAdd");
@@ -84,6 +87,7 @@ public ModelAndView forwardUpdate(@PathVariable("id") String id) {
8487
decoderSecret(saml20Details);
8588
WebContext.setAttribute(saml20Details.getId(), saml20Details.getIcon());
8689
modelAndView.addObject("model",saml20Details);
90+
modelAndView.addObject("maxKeyURI",maxKeyURI);
8791
return modelAndView;
8892
}
8993
/**

0 commit comments

Comments
 (0)