लेखन के समय, स्प्रिंग एसएएमएल संस्करण 1.0.1 पर है। अंतिम। यह बॉक्स से बाहर बहु-किरायेदारी का समर्थन नहीं करता है। मुझे ऊपर व्लादिमीर द्वारा दिए गए सुझावों के अलावा बहु-किरायेदारी हासिल करने का एक और तरीका मिला। यह बहुत ही सरल और सीधा-आगे है और किसी भी स्प्रिंग एसएएमएल कक्षाओं के विस्तार की आवश्यकता नहीं है। इसके अलावा, यह स्प्रिंग SAML के CachingMetadataManager
में उपनामों के अंतर्निर्मित हैंडलिंग का उपयोग करता है।
अपने नियंत्रक में, किरायेदार नाम को अनुरोध से कैप्चर करें और किरायेदार नाम का उपयोग उपनाम के रूप में ExtendedMetadata
ऑब्जेक्ट बनाएं। इसके बाद ExtendedMetadata
में से ExtendedMetadataDelegate
बनाएं और इसे प्रारंभ करें। इसके बाहर इकाई आईडी को पार्स करें और जांचें कि क्या वे MetadataManager
में मौजूद हैं या नहीं। यदि वे मौजूद नहीं हैं, तो प्रदाता जोड़ें और मेटाडेटा रीफ्रेश करें। फिर getEntityIdForAlias()
का उपयोग कर से इकाई आईडी प्राप्त करें।
यहां नियंत्रक के लिए कोड है। टिप्पणियाँ इनलाइन कुछ चेतावनियां समझा रहे हैं:
@Controller
public class SAMLController {
@Autowired
MetadataManager metadataManager;
@Autowired
ParserPool parserPool;
@RequestMapping(value = "/login.do", method = RequestMethod.GET)
public ModelAndView login(HttpServletRequest request, HttpServletResponse response, @RequestParam String tenantName)
throws MetadataProviderException, ServletException, IOException{
//load metadata url using tenant name
String tenantMetadataURL = loadTenantMetadataURL(tenantName);
//Deprecated constructor, needs to change
HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(tenantMetadataURL, 15000);
httpMetadataProvider.setParserPool(parserPool);
//Create extended metadata using tenant name as the alias
ExtendedMetadata metadata = new ExtendedMetadata();
metadata.setLocal(true);
metadata.setAlias(tenantName);
//Create metadata provider and initialize it
ExtendedMetadataDelegate metadataDelegate = new ExtendedMetadataDelegate(httpMetadataProvider, metadata);
metadataDelegate.initialize();
//getEntityIdForAlias() in MetadataManager must only be called after the metadata provider
//is added and the metadata is refreshed. Otherwise, the alias will be mapped to a null
//value. The following code is a roundabout way to figure out whether the provider has already
//been added or not.
//The method parseProvider() has protected scope in MetadataManager so it was copied here
Set<String> newEntityIds = parseProvider(metadataDelegate);
Set<String> existingEntityIds = metadataManager.getIDPEntityNames();
//If one or more IDP entity ids do not exist in metadata manager, assume it's a new provider.
//If we always add a provider without this check, the initialize methods in refreshMetadata()
//ignore the provider in case of a duplicate but the duplicate still gets added to the list
//of providers because of the call to the superclass method addMetadataProvider(). Might be a bug.
if(!existingEntityIds.containsAll(newEntityIds)) {
metadataManager.addMetadataProvider(metadataDelegate);
metadataManager.refreshMetadata();
}
String entityId = metadataManager.getEntityIdForAlias(tenantName);
return new ModelAndView("redirect:/saml/login?idp=" + URLEncoder.encode(entityId, "UTF-8"));
}
private Set<String> parseProvider(MetadataProvider provider) throws MetadataProviderException {
Set<String> result = new HashSet<String>();
XMLObject object = provider.getMetadata();
if (object instanceof EntityDescriptor) {
addDescriptor(result, (EntityDescriptor) object);
} else if (object instanceof EntitiesDescriptor) {
addDescriptors(result, (EntitiesDescriptor) object);
}
return result;
}
private void addDescriptors(Set<String> result, EntitiesDescriptor descriptors) throws MetadataProviderException {
if (descriptors.getEntitiesDescriptors() != null) {
for (EntitiesDescriptor descriptor : descriptors.getEntitiesDescriptors()) {
addDescriptors(result, descriptor);
}
}
if (descriptors.getEntityDescriptors() != null) {
for (EntityDescriptor descriptor : descriptors.getEntityDescriptors()) {
addDescriptor(result, descriptor);
}
}
}
private void addDescriptor(Set<String> result, EntityDescriptor descriptor) throws MetadataProviderException {
String entityID = descriptor.getEntityID();
result.add(entityID);
}
}
मेरा मानना है कि यह सीधे पता लगाना कैसे एक दिया किरायेदार के लिए आईडीपी पाने के लिए की ओपी के समस्या का हल। लेकिन यह केवल एक इकाई आईडी के साथ आईडीपी के लिए काम करेगा।
मैंने अपना स्वयं का SAMLContextProvider बनाया और populatePeerIdentityId को ओवरराइड किया। यह बहुत अच्छा काम किया। एक बार जब मैं किया गया तो मुझे एहसास हुआ कि SAMLContextProvider का उपयोग केवल एसपीओ एसएसओ के दौरान किया जाता है। हम ज्यादातर एसडीओ शुरू किए गए आईडीपी का उपयोग करते हैं, इसलिए मुझे इसे भी कवर करने की आवश्यकता होती है।मैंने आईडीपी इकाई आईडी के खिलाफ आने वाले संदेश की peerEntityID को जांचना समाप्त कर दिया जो कि मेरे कस्टम SAMLAuthenticationProvider में उस किरायेदार के लिए कॉन्फ़िगर किया गया है। – MarcFasel
सेवा प्रदाता को पहचान प्रदाता मानचित्रण की यह विशेषता बहु-किरायेदारी का समर्थन करने के लिए महत्वपूर्ण है। क्या यह आगामी रिलीज में योजनाबद्ध है? – MarcFasel
हम देखेंगे, परियोजना मेरे खाली समय पर निर्भर करती है (यह किसी के द्वारा प्रायोजित नहीं है) और इसमें से अधिकतर नहीं है। बहु-किरायेदारी में सुधार करना कुछ ऐसा है जो मैं करना चाहता हूं। –