SAMLContextProviderImpl

/*
 * Copyright 2011 Vladimir Schaefer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.security.saml.context;

import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
import org.opensaml.saml2.metadata.RoleDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.security.MetadataCredentialResolver;
import org.opensaml.ws.security.ServletRequestX509CredentialAdapter;
import org.opensaml.ws.transport.http.HTTPInTransport;
import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
import org.opensaml.xml.Configuration;
import org.opensaml.xml.encryption.ChainingEncryptedKeyResolver;
import org.opensaml.xml.encryption.InlineEncryptedKeyResolver;
import org.opensaml.xml.encryption.SimpleRetrievalMethodEncryptedKeyResolver;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver;
import org.opensaml.xml.security.trust.ExplicitX509CertificateTrustEngine;
import org.opensaml.xml.security.trust.TrustEngine;
import org.opensaml.xml.security.x509.*;
import org.opensaml.xml.signature.SignatureTrustEngine;
import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
import org.opensaml.xml.signature.impl.PKIXSignatureTrustEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.saml.SAMLEntryPoint;
import org.springframework.security.saml.key.KeyManager;
import org.springframework.security.saml.metadata.ExtendedMetadata;
import org.springframework.security.saml.metadata.MetadataManager;
import org.springframework.security.saml.storage.HttpSessionStorageFactory;
import org.springframework.security.saml.storage.SAMLMessageStorageFactory;
import org.springframework.security.saml.trust.CertPathPKIXTrustEvaluator;
import org.springframework.security.saml.trust.PKIXInformationResolver;
import org.springframework.security.saml.util.SAMLUtil;
import org.springframework.util.Assert;

import javax.net.ssl.HostnameVerifier;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import java.security.cert.X509Certificate;
import java.util.Arrays;

/**类负责解析HttpRequest / Response并确定哪个本地实体(IDP / SP)负责其处理。
 * Class is responsible for parsing HttpRequest/Response and determining which local entity (IDP/SP) is responsible
 * for its handling.
 *
 * @author Vladimir Schaefer
 */
public class SAMLContextProviderImpl implements SAMLContextProvider, InitializingBean {
//说明:Selection of the correct Service Provider instance based on URL is performed inside SAMLContextProviderImpl class.
    protected static final Logger log = LoggerFactory.getLogger(SAMLContextProviderImpl.class);

    // Way to obtain encrypted key info from XML Encryption从XML加密获取加密密钥信息的方法
    private static ChainingEncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver();

    static {
        encryptedKeyResolver.getResolverChain().add(new InlineEncryptedKeyResolver());
        encryptedKeyResolver.getResolverChain().add(new EncryptedElementTypeEncryptedKeyResolver());
        encryptedKeyResolver.getResolverChain().add(new SimpleRetrievalMethodEncryptedKeyResolver());
    }

    protected KeyManager keyManager;
    protected MetadataManager metadata;
    protected MetadataCredentialResolver metadataResolver;//解析凭据?
    protected PKIXValidationInformationResolver pkixResolver;
    protected PKIXTrustEvaluator pkixTrustEvaluator;//使用PKIX验证规则针对一组受信任的PKIXValidationInformation评估X509Credential
    protected SAMLMessageStorageFactory storageFactory = new HttpSessionStorageFactory();

    /**
     * Creates a SAMLContext with local entity values filled. Also request and response must be stored in the context
     * as message transports.
     *
     * @param request  request
     * @param response response
     * @return context
     * @throws MetadataProviderException in case of metadata problems
     */
    public SAMLMessageContext getLocalEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {

        SAMLMessageContext context = new SAMLMessageContext();
        populateGenericContext(request, response, context);//说明:填充 元数据管理器,请求,响应,消息存储方式
        populateLocalEntityId(context, request.getRequestURI());//说明:填充LocalEntityId,LocalEntityRole
        populateLocalContext(context);//看过了
        return context;

    }

    /**创建一个具有本地实体和对等值填充的SAMLContext。 同样,请求和响应也必须作为消息传输存储在上下文中。 当可以从请求中确定本地实体和对等实体时,应使用该属性。
     * Creates a SAMLContext with local entity and peer values filled. Also request and response must be stored in the context
     * as message transports. Should be used when both local entity and peer entity can be determined from the request.
     *
     * @param request  request
     * @param response response
     * @return context
     * @throws MetadataProviderException in case of metadata problems
     */
    public SAMLMessageContext getLocalAndPeerEntity(HttpServletRequest request, HttpServletResponse response) throws MetadataProviderException {

        SAMLMessageContext context = new SAMLMessageContext();
        populateGenericContext(request, response, context);//说明:填充 元数据管理器,请求,响应,消息存储方式
        populateLocalEntityId(context, request.getRequestURI());//说明:填充LocalEntityId,LocalEntityRole
        populateLocalContext(context);
        populatePeerEntityId(context);//说明:填充PeerEntityId,PeerEntityRole
        populatePeerContext(context);
        return context;

    }

    /**首先尝试从请求属性中找到预配置的IDP。 如果未找到,则从请求中加载IDP_PARAMETER;如果不为null,则在我们的信任圈中验证具有该值的IDP是否为有效的IDP。 IDP无效时处理失败。 在上下文中将IDP设置为PeerEntityId。如果request参数为null,则返回默认IDP。
     * First tries to find pre-configured IDP from the request attribute. If not found
     * loads the IDP_PARAMETER from the request and if it is not null verifies whether IDP with this value is valid
     * IDP in our circle of trust. Processing fails when IDP is not valid. IDP is set as PeerEntityId in the context.
     * <p>
     * If request parameter is null the default IDP is returned.
     *
     * @param context context to populate ID for
     * @throws MetadataProviderException in case provided IDP value is invalid
     */
    protected void populatePeerEntityId(SAMLMessageContext context) throws MetadataProviderException {

        HTTPInTransport inTransport = (HTTPInTransport) context.getInboundMessageTransport();
        String entityId;
                                                                                        //说明:"peerEntityId"
        entityId = (String) inTransport.getAttribute(org.springframework.security.saml.SAMLConstants.PEER_ENTITY_ID);
        if (entityId != null) { // Pre-configured entity Id
            log.debug("Using protocol specified IDP {}", entityId);
        } else {
            entityId = inTransport.getParameterValue(SAMLEntryPoint.IDP_PARAMETER);//说明:参数:"idp"
            if (entityId != null) { // IDP from request
                log.debug("Using user specified IDP {} from request", entityId);
                context.setPeerUserSelected(true);
            } else { // Default IDP
                entityId = metadata.getDefaultIDP();//看过了
                log.debug("No IDP specified, using default {}", entityId);
                context.setPeerUserSelected(false);
            }
        }
//说明:填充PeerEntityId,PeerEntityRole
        context.setPeerEntityId(entityId);
        context.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);

    }

    /**根据先前加载的peerEntityId填充有关对等方的其他信息。
     * Populates additional information about the peer based on the previously loaded peerEntityId.
     *
     * @param samlContext to populate
     * @throws MetadataProviderException in case metadata problem is encountered
     */
    protected void populatePeerContext(SAMLMessageContext samlContext) throws MetadataProviderException {
//看过了
        String peerEntityId = samlContext.getPeerEntityId();
        QName peerEntityRole = samlContext.getPeerEntityRole();

        if (peerEntityId == null) {
            throw new MetadataProviderException("Peer entity ID wasn't specified, but is requested");
        }

        EntityDescriptor entityDescriptor = metadata.getEntityDescriptor(peerEntityId);
        RoleDescriptor roleDescriptor = metadata.getRole(peerEntityId, peerEntityRole, SAMLConstants.SAML20P_NS);
        ExtendedMetadata extendedMetadata = metadata.getExtendedMetadata(peerEntityId);

        if (entityDescriptor == null || roleDescriptor == null) {
            throw new MetadataProviderException("Metadata for entity " + peerEntityId + " and role " + peerEntityRole + " wasn't found");
        }

        samlContext.setPeerEntityMetadata(entityDescriptor);
        samlContext.setPeerEntityRoleMetadata(roleDescriptor);
        samlContext.setPeerExtendedMetadata(extendedMetadata);


    }
//说明:填充 元数据管理器,请求,响应,消息存储方式
    protected void populateGenericContext(HttpServletRequest request, HttpServletResponse response, SAMLMessageContext context) throws MetadataProviderException {

        HttpServletRequestAdapter inTransport = new HttpServletRequestAdapter(request);
        HttpServletResponseAdapter outTransport = new HttpServletResponseAdapter(response, request.isSecure());

        // Store attribute which cannot be located from InTransport directly 存储属性
        request.setAttribute(org.springframework.security.saml.SAMLConstants.LOCAL_CONTEXT_PATH, request.getContextPath());
                                                                            //说明:"localContextPath"
        context.setMetadataProvider(metadata);
        context.setInboundMessageTransport(inTransport);
        context.setOutboundMessageTransport(outTransport);

        context.setMessageStorage(storageFactory.getMessageStorage(request));//存入httpsession

    }

    protected void populateLocalContext(SAMLMessageContext context) throws MetadataProviderException {

        populateLocalEntity(context);//说明:填充LocalEntityMetadata,LocalEntityRoleMetadata,LocalExtendedMetadata,LocalSigningCredential
        populateDecrypter(context);//看过了
        populateSSLCredential(context);//本地ssl私钥?
        populatePeerSSLCredential(context);//看不懂啊
        populateTrustEngine(context);//pkix or metaiop 签名用
        populateSSLTrustEngine(context); //pkix or metaiop ssl用
        populateSSLHostnameVerifier(context);//default

    }

    /**方法尝试从请求路径加载localEntityAlias和localEntityRole。 路径应采用以下格式:https(s)://server:port/application/saml/filterName/alias/aliasName/idp|sp?query。 如果路径中缺少别名,则使用默认值。 否则,将localEntityId和sp或idp localEntityRole输入到上下文中。如果未找到别名实体ID,则会引发异常。
     * Method tries to load localEntityAlias and localEntityRole from the request path. Path is supposed to be in format:
     * https(s)://server:port/application/saml/filterName/alias/aliasName/idp|sp?query. In case alias is missing from
     * the path defaults are used. Otherwise localEntityId and sp or idp localEntityRole is entered into the context.
     * <p>
     * In case alias entity id isn't found an exception is raised.
     *
     * @param context     context to populate fields localEntityId and localEntityRole for用于填充字段localEntityId和localEntityRole的上下文
     * @param requestURI context path to parse entityId and entityRole from从中解析entityId和entityRole的上下文路径
     * @throws MetadataProviderException in case entityId can't be populated
     */
    protected void populateLocalEntityId(SAMLMessageContext context, String requestURI) throws MetadataProviderException {
//说明:填充LocalEntityId,LocalEntityRole
        String entityId;
        HTTPInTransport inTransport = (HTTPInTransport) context.getInboundMessageTransport();
        //说明:先从attribute里面拿?
        // Pre-configured entity Id                                                                 "localEntityId"
        entityId = (String) inTransport.getAttribute(org.springframework.security.saml.SAMLConstants.LOCAL_ENTITY_ID);
        if (entityId != null) {
            log.debug("Using protocol specified SP {}", entityId);
            context.setLocalEntityId(entityId);
            context.setLocalEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
            return;
        }

        if (requestURI == null) {
            requestURI = "";
        }

        int filterIndex = requestURI.indexOf("/alias/");
        if (filterIndex != -1) { // EntityId from URL alias

            String localAlias = requestURI.substring(filterIndex + 7);
            QName localEntityRole;
            //说明:/alias/test/idp
            int entityTypePosition = localAlias.lastIndexOf('/');
            if (entityTypePosition != -1) {
                String entityRole = localAlias.substring(entityTypePosition + 1);
                if ("idp".equalsIgnoreCase(entityRole)) {
                    localEntityRole = IDPSSODescriptor.DEFAULT_ELEMENT_NAME;
                } else {
                    localEntityRole = SPSSODescriptor.DEFAULT_ELEMENT_NAME;
                }
                localAlias = localAlias.substring(0, entityTypePosition);
            } else {
                localEntityRole = SPSSODescriptor.DEFAULT_ELEMENT_NAME;
            }


            // Populate entityId
            entityId = metadata.getEntityIdForAlias(localAlias);//一般般

            if (entityId == null) {
                throw new MetadataProviderException("No local entity found for alias " + localAlias + ", verify your configuration.");
            } else {
                log.debug("Using SP {} specified in request with alias {}", entityId, localAlias);
            }

            context.setLocalEntityId(entityId);
            context.setLocalEntityRole(localEntityRole);

        } else { // Defaults

            context.setLocalEntityId(getDefaultLocalEntityId(context, requestURI));
            context.setLocalEntityRole(getDefaultLocalEntityRole(context, requestURI));

        }

    }

    /**如果路径中缺少别名,则返回要为上下文填充的localEntityId
     * Returns localEntityId to be populated for the context in case alias is missing from the path
     * @param context context to retrieve localEntityId for
     * @param requestURI context path to parse entityId from
     * @return localEntityId
     * @throws MetadataProviderException in case entityId can't be retrieved
     */
    protected String getDefaultLocalEntityId(SAMLMessageContext context, String requestURI) throws MetadataProviderException {
        return metadata.getHostedSPName();
    }

    /**如果路径中缺少别名,则返回要为上下文填充的localEntityRole
     * Returns localEntityRole to be populated for the context in case alias is missing from the path
     * @param context context to retrieve localEntityRole for
     * @param requestURI context path to parse entityRole from
     * @return localEntityRole
     * @throws MetadataProviderException in case entityRole can't be retrieved
     */
    protected QName getDefaultLocalEntityRole(SAMLMessageContext context, String requestURI) throws MetadataProviderException {
        return SPSSODescriptor.DEFAULT_ELEMENT_NAME;
    }

    /**方法填充字段localEntityId,localEntityRole,localEntityMetadata,localEntityRoleMetadata和peerEntityRole。 如果设置了字段localAlias,localEntityId,localEntiyRole或peerEntityRole,则使用默认SP和IDP作为对等项的默认值。
     * Method populates fields localEntityId, localEntityRole, localEntityMetadata, localEntityRoleMetadata and peerEntityRole.
     * In case fields localAlias, localEntityId, localEntiyRole or peerEntityRole are set they are used, defaults of default SP and IDP as a peer
     * are used instead.
     *
     * @param samlContext context to populate
     * @throws org.opensaml.saml2.metadata.provider.MetadataProviderException
     *          in case metadata do not contain expected entities or localAlias is specified but not found
     */
    protected void populateLocalEntity(SAMLMessageContext samlContext) throws MetadataProviderException {

        String localEntityId = samlContext.getLocalEntityId();
        QName localEntityRole = samlContext.getLocalEntityRole();

        if (localEntityId == null) {
            throw new MetadataProviderException("No hosted service provider is configured and no alias was selected");
        }
//说明:RoleDescriptor是EntityDescriptor的子类?是的。通过localEntityRole和SAMLConstants.SAML20P_NS过滤出第一个
        EntityDescriptor entityDescriptor = metadata.getEntityDescriptor(localEntityId);
        RoleDescriptor roleDescriptor = metadata.getRole(localEntityId, localEntityRole, SAMLConstants.SAML20P_NS);//
        ExtendedMetadata extendedMetadata = metadata.getExtendedMetadata(localEntityId);

        if (entityDescriptor == null || roleDescriptor == null) {
            throw new MetadataProviderException("Metadata for entity " + localEntityId + " and role " + localEntityRole + " wasn't found");
        }
//说明:填充LocalEntityMetadata,LocalEntityRoleMetadata,LocalExtendedMetadata,LocalSigningCredential
        samlContext.setLocalEntityMetadata(entityDescriptor);
        samlContext.setLocalEntityRoleMetadata(roleDescriptor);
        samlContext.setLocalExtendedMetadata(extendedMetadata);

        if (extendedMetadata.getSigningKey() != null) {
            samlContext.setLocalSigningCredential(keyManager.getCredential(extendedMetadata.getSigningKey()));
        } else {
            samlContext.setLocalSigningCredential(keyManager.getDefaultCredential());//看过了
        }

    }

    /**填充用于根据对等服务器对本机进行身份验证的X509凭据。 使用具有在TlsKey下的扩展元数据中指定的别名的密钥,如果未设置,则使用默认凭据。
     * Populates X509 Credential used to authenticate this machine against peer servers. Uses key with alias specified
     * in extended metadata under TlsKey, when not set uses the default credential.
     *
     * @param samlContext context to populate
     */
    protected void populateSSLCredential(SAMLMessageContext samlContext) {

        X509Credential tlsCredential;
        if (samlContext.getLocalExtendedMetadata().getTlsKey() != null) {
            tlsCredential = (X509Credential) keyManager.getCredential(samlContext.getLocalExtendedMetadata().getTlsKey());
        } else {
            tlsCredential = null;
        }

        samlContext.setLocalSSLCredential(tlsCredential);

    }

    /**使用在上下文提供程序中配置的值填充主机名验证程序。
     * Populates hostname verifier using value configured in the context provider..
     *
     * @param samlContext context to populate
     */
    protected void populateSSLHostnameVerifier(SAMLMessageContext samlContext) {

        HostnameVerifier hostnameVerifier = SAMLUtil.getHostnameVerifier(samlContext.getLocalExtendedMetadata().getSslHostnameVerification());
        samlContext.setGetLocalSSLHostnameVerifier(hostnameVerifier);

    }

    /**尝试使用属性“ javax.servlet.request.X509Certificate”从入站消息传输中加载对等SSL证书。 如果找到,则在上下文中设置peerSSLCredential。
     * Tries to load peer SSL certificate from the inbound message transport using attribute
     * "javax.servlet.request.X509Certificate". If found sets peerSSLCredential in the context.
     *
     * @param samlContext context to populate
     */
    protected void populatePeerSSLCredential(SAMLMessageContext samlContext) {

        X509Certificate[] chain = (X509Certificate[]) samlContext.getInboundMessageTransport().getAttribute(ServletRequestX509CredentialAdapter.X509_CERT_REQUEST_ATTRIBUTE);

        if (chain != null && chain.length > 0) {

            log.debug("Found certificate chain from request {}", chain[0]);
            BasicX509Credential credential = new BasicX509Credential();
            credential.setEntityCertificate(chain[0]);
            credential.setEntityCertificateChain(Arrays.asList(chain));
            samlContext.setPeerSSLCredential(credential);

        }

    }

    /**当扩展元数据中未指定加密凭据时,基于扩展元数据中的设置或使用默认凭据来填充解密器。
     * Populates a decrypter based on settings in the extended metadata or using a default credential when no
     * encryption credential is specified in the extended metadata.
     *
     * @param samlContext context to populate decryptor for.
     */
    protected void populateDecrypter(SAMLMessageContext samlContext) {

        // Locate encryption key for this entity
        Credential encryptionCredential;
        if (samlContext.getLocalExtendedMetadata().getEncryptionKey() != null) {
            encryptionCredential = keyManager.getCredential(samlContext.getLocalExtendedMetadata().getEncryptionKey());
        } else {
            encryptionCredential = keyManager.getDefaultCredential();
        }
        //用于解密加密的XML部件的实体,使用encryptionKeyResolver从加密的XML中提取EncryptedKey,并尝试使用解析器提供的私钥对其进行解密。
        // Entity used for decrypting of encrypted XML parts
        // Extracts EncryptedKey from the encrypted XML using the encryptedKeyResolver and attempts to decrypt it
        // using private keys supplied by the resolver.
        KeyInfoCredentialResolver resolver = new StaticKeyInfoCredentialResolver(encryptionCredential);

        Decrypter decrypter = new Decrypter(null, resolver, encryptedKeyResolver);
        decrypter.setRootInNewDocument(true);

        samlContext.setLocalDecrypter(decrypter);

    }

    /**基于扩展元数据中的设置,可以使用扩展元数据中指定的可信密钥作为锚来创建PKIX信任引擎,或者(默认情况下)使用来自元数据或来自ExtendedMetadata中覆盖的值的数据来创建显式信任引擎。
     * Based on the settings in the extended metadata either creates a PKIX trust engine with trusted keys specified
     * in the extended metadata as anchors or (by default) an explicit trust engine using data from the metadata or
     * from the values overridden in the ExtendedMetadata.
     *
     * @param samlContext context to populate
     */
    protected void populateTrustEngine(SAMLMessageContext samlContext) {
        SignatureTrustEngine engine;
        if ("pkix".equalsIgnoreCase(samlContext.getLocalExtendedMetadata().getSecurityProfile())) {
            engine = new PKIXSignatureTrustEngine(pkixResolver, Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver(), pkixTrustEvaluator, new BasicX509CredentialNameEvaluator());
        } else {
            engine = new ExplicitKeySignatureTrustEngine(metadataResolver, Configuration.getGlobalSecurityConfiguration().getDefaultKeyInfoCredentialResolver());
        }
        samlContext.setLocalTrustEngine(engine);
    }

    /**基于扩展元数据中的设置,可以使用扩展元数据中指定的可信密钥作为锚来创建PKIX信任引擎,或者(默认情况下)使用元数据中的数据或来自ExtendedMetadata中覆盖的值的显式信任引擎来创建显式信任引擎。 信任引擎用于验证SSL连接。
     * Based on the settings in the extended metadata either creates a PKIX trust engine with trusted keys specified
     * in the extended metadata as anchors or (by default) an explicit trust engine using data from the metadata or
     * from the values overridden in the ExtendedMetadata. The trust engine is used to verify SSL connections.
     *
     * @param samlContext context to populate
     */
    protected void populateSSLTrustEngine(SAMLMessageContext samlContext) {
        TrustEngine<X509Credential> engine;
        if ("pkix".equalsIgnoreCase(samlContext.getLocalExtendedMetadata().getSslSecurityProfile())) {
            engine = new PKIXX509CredentialTrustEngine(pkixResolver, pkixTrustEvaluator, new BasicX509CredentialNameEvaluator());
        } else {
            engine = new ExplicitX509CertificateTrustEngine(metadataResolver);
        }
        samlContext.setLocalSSLTrustEngine(engine);
    }

    /**
     * Metadata manager provides information about all available IDP and SP entities.
     *
     * @param metadata metadata mangaer
     */
    @Autowired
    public void setMetadata(MetadataManager metadata) {
        this.metadata = metadata;
    }

    /**
     * Key manager provides information about private certificate and trusted keys provide in addition to
     * cryptographic material present in entity metadata documents.
     *
     * @param keyManager key manager
     */
    @Autowired
    public void setKeyManager(KeyManager keyManager) {
        this.keyManager = keyManager;
    }

    /**
     * Sets resolver used to populate data for PKIX trust engine. Trust anchors are internally cached. They get populated
     * using configured MetadataResolver and enhanced with trustedKeys from the ExtendedMetadata.
     *
     * System uses default configuration when property is not set.
     *
     * Default implementation (org.springframework.security.saml.trust.PKIXInformationResolver) loads trust anchors
     * from both metadata and extended metadata of the peer entity. In case ExtendedMetadata doesn't define any
     * trustedKeys (property trustedKeys is null which is the default), system will use all certificates available
     * in the configured keyStore as trust anchors.
     *
     * @param pkixResolver pkix resolver
     * @see org.springframework.security.saml.trust.PKIXInformationResolver
     */
    public void setPkixResolver(PKIXValidationInformationResolver pkixResolver) {
        this.pkixResolver = pkixResolver;
    }

    /**
     * Trust evaluator is responsible for verifying whether to trust certificate based on PKIX verification.
     *
     * System uses default configuration when property is not set.
     *
     * Default implementation (org.springframework.security.saml.trust.CertPathPKIXTrustEvaluator) uses Java CertPath API
     * to perform the verification. The default implementation can be constructed with an instance of
     * org.opensaml.xml.security.x509.CertPathPKIXValidationOptions which further customizes the PKIX process, e.g. in
     * regard to certificate expiration checking. It is also possible to customize the security provider to use for
     * loading of the CertPath API factories.
     *
     * @param pkixTrustEvaluator pkix trust evaluator
     * @see org.springframework.security.saml.trust.CertPathPKIXTrustEvaluator
     */
    public void setPkixTrustEvaluator(PKIXTrustEvaluator pkixTrustEvaluator) {
        this.pkixTrustEvaluator = pkixTrustEvaluator;
    }

    /**
     * Sets resolver used to populate trusted credentials from XML and Extended metadata. Metadata resolver
     * is used as the only resolver for MetaIOP security profile. It is also used for loading of trusted anchors in
     * the PKIX profile.
     *
     * System uses default configuration when property is not set.
     *
     * Default implementation (org.springframework.security.saml.trust.MetadataCredentialResolver) populates
     * trusted certificates from both peer metadata and peer extended metadata (properties signingKey, encryptionKey
     * and tlsKey).
     *
     * @param metadataResolver metaiop resolver
     * @see org.springframework.security.saml.trust.MetadataCredentialResolver
     */
    public void setMetadataResolver(MetadataCredentialResolver metadataResolver) {
        this.metadataResolver = metadataResolver;
    }

    /**
     * Implementation of the SAML message storage factory providing custom mechanism for storage
     * of SAML messages such as http session, cookies or no storage at all.
     *
     * @param storageFactory storage factory
     */
    @Autowired(required = false)
    public void setStorageFactory(SAMLMessageStorageFactory storageFactory) {
        this.storageFactory = storageFactory;
    }

    /**
     * Verifies that required entities were autowired or set and initializes resolvers used to construct trust engines.
     */
    public void afterPropertiesSet() throws ServletException {

        Assert.notNull(keyManager, "Key manager must be set");
        Assert.notNull(metadata, "Metadata must be set");
        Assert.notNull(storageFactory, "MessageStorageFactory must be set");

        if (metadataResolver == null) {
            MetadataCredentialResolver resolver = new org.springframework.security.saml.trust.MetadataCredentialResolver(metadata, keyManager);
            resolver.setMeetAllCriteria(false);
            resolver.setUnevaluableSatisfies(true);
            this.metadataResolver = resolver;
        }

        if (pkixResolver == null) {
            pkixResolver = new PKIXInformationResolver(metadataResolver, metadata, keyManager);
        }

        if (pkixTrustEvaluator == null) {
            pkixTrustEvaluator = new CertPathPKIXTrustEvaluator();
        }

    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值