Yazım sırasında, Spring SAML, 1.0.1.FINAL sürümündedir. Kutudan temiz bir şekilde çok kiracılığı desteklemez. Yukarıdaki Vladimir tarafından verilen önerilerin dışında çok kiracılığa ulaşmak için başka bir yol buldum. Çok basit ve düz ileri ve herhangi bir Spring SAML sınıfının genişletilmesini gerektirmez. Ayrıca, Spring SAML'nin CachingMetadataManager
numaralı telefondaki takma adların kullanımını da kullanır. Kumandanızda olarak
, istekten kiracı adını yakalamak ve takma ad olarak kiracı adını kullanarak bir ExtendedMetadata
nesne oluşturmak. Ardından, ExtendedMetadata
'dan bir ExtendedMetadataDelegate
oluşturun ve ilklendirin. Varlık kimliklerini bunun dışında ayrıştırın ve MetadataManager
içinde olup olmadığını kontrol edin. Varsa, sağlayıcıyı ekleyin ve meta verileri yenileyin. Ardından, getEntityIdForAlias()
'u kullanarak varlık kimliğini MetadataManager
'dan alın.
Denetleyicinin kodu şöyledir. satır içi bazı uyarılar açıklayan yorumlar vardır:
@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);
}
}
bu direkt olarak belirli bir kiracı için IDP almak için nasıl bulmaktan OP'ın sorunu çözer inanıyoruz. Ancak bu, yalnızca tek bir varlık kimliğine sahip IDP'ler için çalışacaktır.
Kendi SAMLContextProvider'mı oluşturdum ve populatePeerIdentityId'yi geçersiz kıldım. Bu harika çalıştı. Bir kez bittikten sonra SAMLContextProvider'ın sadece SP tarafından başlatılan SSO sırasında kullanıldığını fark ettim. Çoğunlukla IDP tarafından başlatılan SSO kullanıyoruz, bu yüzden bunu da kapsamam gerekiyordu.Gelen iletinin peerEntityID değerini, özel SAMLAuthenticationProvider öğesinde bu kiracı için yapılandırılan IDP varlık kimliğine karşı kontrol ettim. – MarcFasel
Kimlik sağlayıcıyı servis sağlayıcıya eşleme özelliğinin bu özelliği, çoklu kiralamayı desteklemenin anahtarıdır. Bu gelecek sürümlerde mi planlanıyor? – MarcFasel
Göreceğiz, proje boş zamanıma bağlı (herkes tarafından desteklenmiyor) ve fazla bir şey yok. Çoklu kiracılığı geliştirmek, yapmak istediğim bir şeydir. –