Zum Zeitpunkt des Schreibens befindet sich Spring SAML in der Version 1.0.1.FINAL. Die Multi-Tenancy-Funktion wird nicht sofort unterstützt. Ich habe einen anderen Weg gefunden, um eine Mehrfachmiete zu erreichen, abgesehen von den Vorschlägen von Vladimir oben. Es ist sehr einfach und unkompliziert und erfordert keine Erweiterung von Spring SAML-Klassen. Darüber hinaus nutzt Spring SAML die integrierte Handhabung von Aliasen in CachingMetadataManager
.
In Ihrem Controller, erfassen die Mieter Namen von der Anfrage und erstellen Sie ein Objekt ExtendedMetadata
die Mieter Namen als Alias. Als nächstes erstellen Sie eine ExtendedMetadataDelegate
aus der ExtendedMetadata
und initialisieren Sie es. Analysieren Sie die Entity-IDs und prüfen Sie, ob sie in MetadataManager
vorhanden sind. Wenn sie nicht vorhanden sind, fügen Sie den Anbieter hinzu und aktualisieren Sie die Metadaten. Dann erhalten Sie die Entity-ID von MetadataManager
mit getEntityIdForAlias()
.
Hier ist der Code für den Controller. Es gibt Kommentare Inline einige Einschränkungen zu erklären:
@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);
}
}
Ich glaube, das direkt das Problem des OP löst herauszufinden, wie für einen bestimmten Mieter das IDP zu bekommen. Dies funktioniert jedoch nur für IDPs mit einer einzelnen Entitäts-ID.
Ich habe meinen eigenen SAMLContextProvider erstellt und die populatePeerIdentityId überschrieben. Das hat super funktioniert. Sobald ich fertig war, erkannte ich, dass der SAMLContextProvider nur während SP-initiierten SSO verwendet wird. Wir verwenden meistens IDP-initiierte SSO, also musste ich das ebenfalls abdecken.Am Ende habe ich die PeerEntityID der eingehenden Nachricht mit der IDP-Entitäts-ID verglichen, die für diesen Mandanten in meinem benutzerdefinierten SAMLAuthenticationProvider konfiguriert ist. – MarcFasel
Diese Funktion zum Zuordnen von Identity Provider zu Service Provider ist der Schlüssel zur Unterstützung von Mandantenfähigkeit. Ist das in kommenden Releases geplant? – MarcFasel
Wir werden sehen, das Projekt hängt von meiner Freizeit ab (es wird von niemandem gesponsert) und es gibt nicht viel davon. Die Verbesserung der Mandantenfähigkeit möchte ich gerne tun. –