spring-security saml2: как получить текущего пользователя? - PullRequest
0 голосов
/ 15 октября 2019

Я работаю с провайдером spring-security и spring-security-saml2-service с версиями 5.2.0.RELEASE. Я пытаюсь после аутентификации IDP получить текущее утверждение, чтобы сопоставить его с пользователем в нашей локальной системе. Я использую этот код для получения объекта Saml2Authentication

@Component
@Log4j
public class EventListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
    @Override
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent interactiveAuthenticationSuccessEvent) {
        Object principal = interactiveAuthenticationSuccessEvent.getAuthentication().getPrincipal();
        Saml2Authentication authentication = (Saml2Authentication)interactiveAuthenticationSuccessEvent.getAuthentication()

Но я не могу получить пользователя. Я могу получить ответ saml2 (authentication.getSaml2Response), но я не уверен, как получить утверждение с идентификатором пользователя.

Действительно, я хотел бы сделать Получить атрибуты и NameID изответ SAML (XML) в коде Java. Не уверен, что в Spring-Security есть что-то, что может мне помочь.

Обновление Поэтому после небольшой работы я получаю атрибуты, используя библиотеку OpenSAML и анализируя ответ SAMLv2. Я не знаю, если это правильный способ сделать это

@Override
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent interactiveAuthenticationSuccessEvent) {
        Saml2Authentication authentication = (Saml2Authentication) interactiveAuthenticationSuccessEvent.getAuthentication();
        try {

            Document messageDoc;
            BasicParserPool basicParserPool = new BasicParserPool();
            basicParserPool.initialize();
            InputStream inputStream = new ByteArrayInputStream(authentication.getSaml2Response().getBytes());
            messageDoc = basicParserPool.parse(inputStream);
            Element messageElem = messageDoc.getDocumentElement();
            Unmarshaller unmarshaller = XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(messageElem);
            XMLObject samlObject = unmarshaller.unmarshall(messageElem);
            Response response = (Response) samlObject;
            response.getAssertions().forEach(assertion -> {
                assertion.getAttributeStatements().forEach(attributeStatement ->
                {
                    attributeStatement.getAttributes().forEach(attribute -> {
                        log.error("Names:" + attribute.getName() + getAttributesList(attribute.getAttributeValues()));
                    });
                });
            });
        } catch (Exception e) {
            log.error(e);
        }
    }

    private List<String> getAttributesList(Collection<XMLObject> collection) {
        return collection.stream().map(this::getAttributeValue)
                .collect(Collectors.toList());
    }

    private String getAttributeValue(XMLObject attributeValue) {
        return attributeValue == null ?
                null :
                attributeValue instanceof XSString ?
                        getStringAttributeValue((XSString) attributeValue) :
                        attributeValue instanceof XSAnyImpl ?
                                getAnyAttributeValue((XSAnyImpl) attributeValue) :
                                attributeValue.toString();
    }

    private String getStringAttributeValue(XSString attributeValue) {
        return attributeValue.getValue();
    }

    private String getAnyAttributeValue(XSAnyImpl attributeValue) {
        return attributeValue.getTextContent();
    }

1 Ответ

1 голос
/ 17 октября 2019

По умолчанию Spring SAML Security использует значение NameID в элементе Subject для установки «имени пользователя». Если 'transient NameID format', значение должно быть разным / уникальным для каждого потока SSO для спецификации SAML.

Вы можете реализовать свой собственный UserDetailsService, который реализует org.springframework.security.saml.userdetails.SAMLUserDetailsService в методе loadUserBySAML youможет извлечь атрибуты SAML

@Override
public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
  final List<Attribute> attributesFromAttributeStatement = credential.getAttributes();

  final String userName = getUserNameValueFromAttribute(attributesFromAttributeStatement);

  // if needed calculate authorities
  final List<GrantedAuthority> grantedAuthorities = getGrantedAuthorities();
  final User authenticatedUser = new User(userName, "", grantedAuthorities);
  return authenticatedUser;
}
...