Package org.springframework.security.config.http

Source Code of org.springframework.security.config.http.HeadersBeanDefinitionParser

/*
* Copyright 2002-2012 the original author or authors.
*
* 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
*
*      http://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.config.http;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.header.writers.CacheControlHeadersWriter;
import org.springframework.security.web.header.writers.HstsHeaderWriter;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.security.web.header.writers.XContentTypeOptionsHeaderWriter;
import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.RegExpAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.WhiteListedAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;

/**
* Parser for the {@code HeadersFilter}.
*
* @author Marten Deinum
* @since 3.2
*/
public class HeadersBeanDefinitionParser implements BeanDefinitionParser {

    private static final String ATT_ENABLED = "enabled";
    private static final String ATT_BLOCK = "block";

    private static final String ATT_POLICY = "policy";
    private static final String ATT_STRATEGY = "strategy";
    private static final String ATT_FROM_PARAMETER = "from-parameter";

    private static final String ATT_NAME = "name";
    private static final String ATT_VALUE = "value";
    private static final String ATT_REF = "ref";

    private static final String ATT_INCLUDE_SUBDOMAINS = "include-subdomains";
    private static final String ATT_MAX_AGE_SECONDS = "max-age-seconds";
    private static final String ATT_REQUEST_MATCHER_REF = "request-matcher-ref";

    private static final String CACHE_CONTROL_ELEMENT = "cache-control";

    private static final String HSTS_ELEMENT = "hsts";

    private static final String XSS_ELEMENT = "xss-protection";
    private static final String CONTENT_TYPE_ELEMENT = "content-type-options";
    private static final String FRAME_OPTIONS_ELEMENT = "frame-options";
    private static final String GENERIC_HEADER_ELEMENT = "header";

    private static final String ALLOW_FROM = "ALLOW-FROM";

    private ManagedList<BeanMetadataElement> headerWriters;

    public BeanDefinition parse(Element element, ParserContext parserContext) {
        headerWriters = new ManagedList<BeanMetadataElement>();
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(HeaderWriterFilter.class);

        parseCacheControlElement(element);
        parseHstsElement(element);
        parseXssElement(element, parserContext);
        parseFrameOptionsElement(element, parserContext);
        parseContentTypeOptionsElement(element);

        parseHeaderElements(element);

        if(headerWriters.isEmpty()) {
            addCacheControl();
            addHsts(null);
            addContentTypeOptions();

            BeanDefinitionBuilder frameOptions = BeanDefinitionBuilder.genericBeanDefinition(XFrameOptionsHeaderWriter.class);
            frameOptions.addConstructorArgValue("DENY");
            headerWriters.add(frameOptions.getBeanDefinition());

            BeanDefinitionBuilder xss = BeanDefinitionBuilder.genericBeanDefinition(XXssProtectionHeaderWriter.class);
            headerWriters.add(xss.getBeanDefinition());
        }
        builder.addConstructorArgValue(headerWriters);
        return builder.getBeanDefinition();
    }

    private void parseCacheControlElement(Element element) {
        Element cacheControlElement = DomUtils.getChildElementByTagName(element, CACHE_CONTROL_ELEMENT);
        if (cacheControlElement != null) {
            addCacheControl();
        }
    }

    private void addCacheControl() {
        BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(CacheControlHeadersWriter.class);
        headerWriters.add(headersWriter.getBeanDefinition());
    }

    private void parseHstsElement(Element element) {
        Element hstsElement = DomUtils.getChildElementByTagName(element, HSTS_ELEMENT);
        if (hstsElement != null) {
            addHsts(hstsElement);
        }
    }

    private void addHsts(Element hstsElement) {
        BeanDefinitionBuilder headersWriter = BeanDefinitionBuilder.genericBeanDefinition(HstsHeaderWriter.class);
        if(hstsElement != null) {
            String includeSubDomains = hstsElement.getAttribute(ATT_INCLUDE_SUBDOMAINS);
            if(StringUtils.hasText(includeSubDomains)) {
                headersWriter.addPropertyValue("includeSubDomains", includeSubDomains);
            }
            String maxAgeSeconds = hstsElement.getAttribute(ATT_MAX_AGE_SECONDS);
            if(StringUtils.hasText(maxAgeSeconds)) {
                headersWriter.addPropertyValue("maxAgeInSeconds", maxAgeSeconds);
            }
            String requestMatcherRef = hstsElement.getAttribute(ATT_REQUEST_MATCHER_REF);
            if(StringUtils.hasText(requestMatcherRef)) {
                headersWriter.addPropertyReference("requestMatcher", requestMatcherRef);
            }
        }
        headerWriters.add(headersWriter.getBeanDefinition());
    }

    private void parseHeaderElements(Element element) {
        List<Element> headerElts = DomUtils.getChildElementsByTagName(element, GENERIC_HEADER_ELEMENT);
        for (Element headerElt : headerElts) {
            String headerFactoryRef = headerElt.getAttribute(ATT_REF);
            if (StringUtils.hasText(headerFactoryRef)) {
                headerWriters.add(new RuntimeBeanReference(headerFactoryRef));
            } else {
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(StaticHeadersWriter.class);
                builder.addConstructorArgValue(headerElt.getAttribute(ATT_NAME));
                builder.addConstructorArgValue(headerElt.getAttribute(ATT_VALUE));
                headerWriters.add(builder.getBeanDefinition());
            }
        }
    }

    private void parseContentTypeOptionsElement(Element element) {
        Element contentTypeElt = DomUtils.getChildElementByTagName(element, CONTENT_TYPE_ELEMENT);
        if (contentTypeElt != null) {
            addContentTypeOptions();
        }
    }

    private void addContentTypeOptions() {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XContentTypeOptionsHeaderWriter.class);
        headerWriters.add(builder.getBeanDefinition());
    }

    private void parseFrameOptionsElement(Element element, ParserContext parserContext) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XFrameOptionsHeaderWriter.class);

        Element frameElt = DomUtils.getChildElementByTagName(element, FRAME_OPTIONS_ELEMENT);
        if (frameElt != null) {
            String header = getAttribute(frameElt, ATT_POLICY, "DENY");
            if (ALLOW_FROM.equals(header) ) {
                String strategyRef = getAttribute(frameElt, ATT_REF, null);
                String strategy = getAttribute(frameElt, ATT_STRATEGY, null);

                if (StringUtils.hasText(strategy) && StringUtils.hasText(strategyRef)) {
                    parserContext.getReaderContext().error("Only one of 'strategy' or 'strategy-ref' can be set.",
                            frameElt);
                } else if (strategyRef != null) {
                    builder.addConstructorArgReference(strategyRef);
                } else if (strategy != null) {
                    String value = getAttribute(frameElt, ATT_VALUE, null);
                    if (!StringUtils.hasText(value)) {
                        parserContext.getReaderContext().error("Strategy requires a 'value' to be set.", frameElt);
                    }
                    // static, whitelist, regexp
                    if ("static".equals(strategy)) {
                        try {
                            builder.addConstructorArgValue(new StaticAllowFromStrategy(new URI(value)));
                        } catch (URISyntaxException e) {
                            parserContext.getReaderContext().error(
                                    "'value' attribute doesn't represent a valid URI.", frameElt, e);
                        }
                    } else {
                        BeanDefinitionBuilder allowFromStrategy;
                        if ("whitelist".equals(strategy)) {
                            allowFromStrategy =  BeanDefinitionBuilder.rootBeanDefinition(WhiteListedAllowFromStrategy.class);
                            allowFromStrategy.addConstructorArgValue(StringUtils.commaDelimitedListToSet(value));
                        } else {
                            allowFromStrategy =  BeanDefinitionBuilder.rootBeanDefinition(RegExpAllowFromStrategy.class);
                            allowFromStrategy.addConstructorArgValue(value);
                        }
                        String fromParameter = getAttribute(frameElt, ATT_FROM_PARAMETER, "from");
                        allowFromStrategy.addPropertyValue("allowFromParameterName", fromParameter);
                        builder.addConstructorArgValue(allowFromStrategy.getBeanDefinition());
                    }
                } else {
                    parserContext.getReaderContext().error("One of 'strategy' and 'strategy-ref' must be set.",
                            frameElt);
                }
            } else {
                builder.addConstructorArgValue(header);
            }
            headerWriters.add(builder.getBeanDefinition());
        }
    }

    private void parseXssElement(Element element, ParserContext parserContext) {
        Element xssElt = DomUtils.getChildElementByTagName(element, XSS_ELEMENT);
        if (xssElt != null) {
            String enabled = xssElt.getAttribute(ATT_ENABLED);
            String block = xssElt.getAttribute(ATT_BLOCK);

            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XXssProtectionHeaderWriter.class);
            if(StringUtils.hasText(enabled)) {
                builder.addPropertyValue("enabled", enabled);
            }
            if(StringUtils.hasText(block)) {
                builder.addPropertyValue("block", block);
            }
            headerWriters.add(builder.getBeanDefinition());
        }
    }

    private String getAttribute(Element element, String name, String defaultValue) {
        String value = element.getAttribute(name);
        if (StringUtils.hasText(value)) {
            return value;
        } else {
            return defaultValue;
        }
    }
}
TOP

Related Classes of org.springframework.security.config.http.HeadersBeanDefinitionParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.