Move Web Access API
Issue gh-17847
This commit is contained in:
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.web.access;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
/**
|
||||
* Allows users to determine whether they have privileges for a given web URI.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
* @deprecated Use {@link AuthorizationManagerWebInvocationPrivilegeEvaluator} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class DefaultWebInvocationPrivilegeEvaluator implements WebInvocationPrivilegeEvaluator, ServletContextAware {
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(DefaultWebInvocationPrivilegeEvaluator.class);
|
||||
|
||||
private final AbstractSecurityInterceptor securityInterceptor;
|
||||
|
||||
private @Nullable ServletContext servletContext;
|
||||
|
||||
public DefaultWebInvocationPrivilegeEvaluator(AbstractSecurityInterceptor securityInterceptor) {
|
||||
Assert.notNull(securityInterceptor, "SecurityInterceptor cannot be null");
|
||||
Assert.isTrue(FilterInvocation.class.equals(securityInterceptor.getSecureObjectClass()),
|
||||
"AbstractSecurityInterceptor does not support FilterInvocations");
|
||||
Assert.notNull(securityInterceptor.getAccessDecisionManager(),
|
||||
"AbstractSecurityInterceptor must provide a non-null AccessDecisionManager");
|
||||
this.securityInterceptor = securityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI.
|
||||
* @param uri the URI excluding the context path (a default context path setting will
|
||||
* be used)
|
||||
*/
|
||||
@Override
|
||||
public boolean isAllowed(String uri, @Nullable Authentication authentication) {
|
||||
return isAllowed(null, uri, null, authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the user represented by the supplied <tt>Authentication</tt>
|
||||
* object is allowed to invoke the supplied URI, with the given .
|
||||
* <p>
|
||||
* Note the default implementation of <tt>FilterInvocationSecurityMetadataSource</tt>
|
||||
* disregards the <code>contextPath</code> when evaluating which secure object
|
||||
* metadata applies to a given request URI, so generally the <code>contextPath</code>
|
||||
* is unimportant unless you are using a custom
|
||||
* <code>FilterInvocationSecurityMetadataSource</code>.
|
||||
* @param uri the URI excluding the context path
|
||||
* @param contextPath the context path (may be null, in which case a default value
|
||||
* will be used).
|
||||
* @param method the HTTP method (or null, for any method)
|
||||
* @param authentication the <tt>Authentication</tt> instance whose authorities should
|
||||
* be used in evaluation whether access should be granted.
|
||||
* @return true if access is allowed, false if denied
|
||||
*/
|
||||
@Override
|
||||
public boolean isAllowed(@Nullable String contextPath, String uri, @Nullable String method,
|
||||
@Nullable Authentication authentication) {
|
||||
Assert.notNull(uri, "uri parameter is required");
|
||||
FilterInvocation filterInvocation = new FilterInvocation(contextPath, uri, method, this.servletContext);
|
||||
Collection<ConfigAttribute> attributes = this.securityInterceptor.obtainSecurityMetadataSource()
|
||||
.getAttributes(filterInvocation);
|
||||
if (attributes == null) {
|
||||
return (!this.securityInterceptor.isRejectPublicInvocations());
|
||||
}
|
||||
if (authentication == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
this.securityInterceptor.getAccessDecisionManager().decide(authentication, filterInvocation, attributes);
|
||||
return true;
|
||||
}
|
||||
catch (AccessDeniedException ex) {
|
||||
logger.debug(LogMessage.format("%s denied for %s", filterInvocation, authentication), ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.PortMapperImpl;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @deprecated please use
|
||||
* {@link org.springframework.security.web.transport.HttpsRedirectFilter} and its
|
||||
* associated {@link PortMapper}
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AbstractRetryEntryPoint implements ChannelEntryPoint {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private PortMapper portMapper = new PortMapperImpl();
|
||||
|
||||
/**
|
||||
* The scheme ("http://" or "https://")
|
||||
*/
|
||||
private final String scheme;
|
||||
|
||||
/**
|
||||
* The standard port for the scheme (80 for http, 443 for https)
|
||||
*/
|
||||
private final int standardPort;
|
||||
|
||||
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
public AbstractRetryEntryPoint(String scheme, int standardPort) {
|
||||
this.scheme = scheme;
|
||||
this.standardPort = standardPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
String queryString = request.getQueryString();
|
||||
String redirectUrl = request.getRequestURI() + ((queryString != null) ? ("?" + queryString) : "");
|
||||
Integer currentPort = this.portMapper.getServerPort(request);
|
||||
Integer redirectPort = getMappedPort(currentPort);
|
||||
if (redirectPort != null) {
|
||||
boolean includePort = redirectPort != this.standardPort;
|
||||
String port = (includePort) ? (":" + redirectPort) : "";
|
||||
redirectUrl = this.scheme + request.getServerName() + port + redirectUrl;
|
||||
}
|
||||
this.logger.debug(LogMessage.format("Redirecting to: %s", redirectUrl));
|
||||
this.redirectStrategy.sendRedirect(request, response, redirectUrl);
|
||||
}
|
||||
|
||||
protected abstract @Nullable Integer getMappedPort(Integer mapFromPort);
|
||||
|
||||
protected final PortMapper getPortMapper() {
|
||||
return this.portMapper;
|
||||
}
|
||||
|
||||
public void setPortMapper(PortMapper portMapper) {
|
||||
Assert.notNull(portMapper, "portMapper cannot be null");
|
||||
this.portMapper = portMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strategy to be used for redirecting to the required channel URL. A
|
||||
* {@code DefaultRedirectStrategy} instance will be used if not set.
|
||||
* @param redirectStrategy the strategy instance to which the URL will be passed.
|
||||
*/
|
||||
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
|
||||
Assert.notNull(redirectStrategy, "redirectStrategy cannot be null");
|
||||
this.redirectStrategy = redirectStrategy;
|
||||
}
|
||||
|
||||
protected final RedirectStrategy getRedirectStrategy() {
|
||||
return this.redirectStrategy;
|
||||
}
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Decides whether a web channel provides sufficient security.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated no replacement is planned, though consider using a custom
|
||||
* {@link RequestMatcher} for any sophisticated decision-making
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ChannelDecisionManager {
|
||||
|
||||
/**
|
||||
* Decided whether the presented {@link FilterInvocation} provides the appropriate
|
||||
* level of channel security based on the requested list of <tt>ConfigAttribute</tt>s.
|
||||
*
|
||||
*/
|
||||
void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>ChannelDecisionManager</code> is able to process the
|
||||
* passed <code>ConfigAttribute</code>.
|
||||
* <p>
|
||||
* This allows the <code>ChannelProcessingFilter</code> to check every configuration
|
||||
* attribute can be consumed by the configured <code>ChannelDecisionManager</code>.
|
||||
* </p>
|
||||
* @param attribute a configuration attribute that has been configured against the
|
||||
* <code>ChannelProcessingFilter</code>
|
||||
* @return true if this <code>ChannelDecisionManager</code> can support the passed
|
||||
* configuration attribute
|
||||
*/
|
||||
boolean supports(ConfigAttribute attribute);
|
||||
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ChannelDecisionManager}.
|
||||
* <p>
|
||||
* Iterates through each configured {@link ChannelProcessor}. If a
|
||||
* <code>ChannelProcessor</code> has any issue with the security of the request, it should
|
||||
* cause a redirect, exception or whatever other action is appropriate for the
|
||||
* <code>ChannelProcessor</code> implementation.
|
||||
* <p>
|
||||
* Once any response is committed (ie a redirect is written to the response object), the
|
||||
* <code>ChannelDecisionManagerImpl</code> will not iterate through any further
|
||||
* <code>ChannelProcessor</code>s.
|
||||
* <p>
|
||||
* The attribute "ANY_CHANNEL" if applied to a particular URL, the iteration through the
|
||||
* channel processors will be skipped (see SEC-494, SEC-335).
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated no replacement is planned, though consider using a custom
|
||||
* {@link RequestMatcher} for any sophisticated decision-making
|
||||
*/
|
||||
@Deprecated
|
||||
@NullUnmarked
|
||||
public class ChannelDecisionManagerImpl implements ChannelDecisionManager, InitializingBean {
|
||||
|
||||
public static final String ANY_CHANNEL = "ANY_CHANNEL";
|
||||
|
||||
private List<ChannelProcessor> channelProcessors;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notEmpty(this.channelProcessors, "A list of ChannelProcessors is required");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
|
||||
throws IOException, ServletException {
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (ANY_CHANNEL.equals(attribute.getAttribute())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (ChannelProcessor processor : this.channelProcessors) {
|
||||
processor.decide(invocation, config);
|
||||
if (invocation.getResponse().isCommitted()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected @Nullable List<ChannelProcessor> getChannelProcessors() {
|
||||
return this.channelProcessors;
|
||||
}
|
||||
|
||||
@SuppressWarnings("cast")
|
||||
public void setChannelProcessors(List<?> channelProcessors) {
|
||||
Assert.notEmpty(channelProcessors, "A list of ChannelProcessors is required");
|
||||
this.channelProcessors = new ArrayList<>(channelProcessors.size());
|
||||
for (Object currentObject : channelProcessors) {
|
||||
Assert.isInstanceOf(ChannelProcessor.class, currentObject, () -> "ChannelProcessor "
|
||||
+ currentObject.getClass().getName() + " must implement ChannelProcessor");
|
||||
this.channelProcessors.add((ChannelProcessor) currentObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if (ANY_CHANNEL.equals(attribute.getAttribute())) {
|
||||
return true;
|
||||
}
|
||||
for (ChannelProcessor processor : this.channelProcessors) {
|
||||
if (processor.supports(attribute)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.web.PortMapper;
|
||||
|
||||
/**
|
||||
* May be used by a {@link ChannelProcessor} to launch a web channel.
|
||||
*
|
||||
* <p>
|
||||
* <code>ChannelProcessor</code>s can elect to launch a new web channel directly, or they
|
||||
* can delegate to another class. The <code>ChannelEntryPoint</code> is a pluggable
|
||||
* interface to assist <code>ChannelProcessor</code>s in performing this delegation.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated please use
|
||||
* {@link org.springframework.security.web.transport.HttpsRedirectFilter} and its
|
||||
* associated {@link PortMapper}
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ChannelEntryPoint {
|
||||
|
||||
/**
|
||||
* Commences a secure channel.
|
||||
* <p>
|
||||
* Implementations should modify the headers on the <code>ServletResponse</code> as
|
||||
* necessary to commence the user agent using the implementation's supported channel
|
||||
* type.
|
||||
* @param request that a <code>ChannelProcessor</code> has rejected
|
||||
* @param response so that the user agent can begin using a new channel
|
||||
*
|
||||
*/
|
||||
void commence(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
|
||||
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
/**
|
||||
* Ensures a web request is delivered over the required channel.
|
||||
* <p>
|
||||
* Internally uses a {@link FilterInvocation} to represent the request, allowing a
|
||||
* {@code FilterInvocationSecurityMetadataSource} to be used to lookup the attributes
|
||||
* which apply.
|
||||
* <p>
|
||||
* Delegates the actual channel security decisions and necessary actions to the configured
|
||||
* {@link ChannelDecisionManager}. If a response is committed by the
|
||||
* {@code ChannelDecisionManager}, the filter chain will not proceed.
|
||||
* <p>
|
||||
* The most common usage is to ensure that a request takes place over HTTPS, where the
|
||||
* {@link ChannelDecisionManagerImpl} is configured with a {@link SecureChannelProcessor}
|
||||
* and an {@link InsecureChannelProcessor}. A typical configuration would be
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* <bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
|
||||
* <property name="channelDecisionManager" ref="channelDecisionManager"/>
|
||||
* <property name="securityMetadataSource">
|
||||
* <security:filter-security-metadata-source request-matcher="regex">
|
||||
* <security:intercept-url pattern="\A/secure/.*\Z" access="REQUIRES_SECURE_CHANNEL"/>
|
||||
* <security:intercept-url pattern="\A/login.jsp.*\Z" access="REQUIRES_SECURE_CHANNEL"/>
|
||||
* <security:intercept-url pattern="\A/.*\Z" access="ANY_CHANNEL"/>
|
||||
* </security:filter-security-metadata-source>
|
||||
* </property>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl">
|
||||
* <property name="channelProcessors">
|
||||
* <list>
|
||||
* <ref bean="secureChannelProcessor"/>
|
||||
* <ref bean="insecureChannelProcessor"/>
|
||||
* </list>
|
||||
* </property>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="secureChannelProcessor"
|
||||
* class="org.springframework.security.web.access.channel.SecureChannelProcessor"/>
|
||||
* <bean id="insecureChannelProcessor"
|
||||
* class="org.springframework.security.web.access.channel.InsecureChannelProcessor"/>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* which would force the login form and any access to the {@code /secure} path to be made
|
||||
* over HTTPS.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated see {@link org.springframework.security.web.transport.HttpsRedirectFilter}
|
||||
*/
|
||||
@Deprecated
|
||||
public class ChannelProcessingFilter extends GenericFilterBean {
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private ChannelDecisionManager channelDecisionManager;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private FilterInvocationSecurityMetadataSource securityMetadataSource;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(this.securityMetadataSource, "securityMetadataSource must be specified");
|
||||
Assert.notNull(this.channelDecisionManager, "channelDecisionManager must be specified");
|
||||
Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAllConfigAttributes();
|
||||
if (attributes == null) {
|
||||
this.logger.warn("Could not validate configuration attributes as the "
|
||||
+ "FilterInvocationSecurityMetadataSource did not return any attributes");
|
||||
return;
|
||||
}
|
||||
Set<ConfigAttribute> unsupportedAttributes = getUnsupportedAttributes(attributes);
|
||||
Assert.isTrue(unsupportedAttributes.isEmpty(),
|
||||
() -> "Unsupported configuration attributes: " + unsupportedAttributes);
|
||||
this.logger.info("Validated configuration attributes");
|
||||
}
|
||||
|
||||
private Set<ConfigAttribute> getUnsupportedAttributes(Collection<ConfigAttribute> attrDefs) {
|
||||
Set<ConfigAttribute> unsupportedAttributes = new HashSet<>();
|
||||
for (ConfigAttribute attr : attrDefs) {
|
||||
if (!this.channelDecisionManager.supports(attr)) {
|
||||
unsupportedAttributes.add(attr);
|
||||
}
|
||||
}
|
||||
return unsupportedAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
FilterInvocation filterInvocation = new FilterInvocation(request, response, chain);
|
||||
Collection<ConfigAttribute> attributes = this.securityMetadataSource.getAttributes(filterInvocation);
|
||||
if (attributes != null) {
|
||||
this.logger.debug(LogMessage.format("Request: %s; ConfigAttributes: %s", filterInvocation, attributes));
|
||||
this.channelDecisionManager.decide(filterInvocation, attributes);
|
||||
@Nullable HttpServletResponse channelResponse = filterInvocation.getResponse();
|
||||
Assert.notNull(channelResponse, "HttpServletResponse is required");
|
||||
if (channelResponse.isCommitted()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
protected @Nullable ChannelDecisionManager getChannelDecisionManager() {
|
||||
return this.channelDecisionManager;
|
||||
}
|
||||
|
||||
protected FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
|
||||
return this.securityMetadataSource;
|
||||
}
|
||||
|
||||
public void setChannelDecisionManager(ChannelDecisionManager channelDecisionManager) {
|
||||
this.channelDecisionManager = channelDecisionManager;
|
||||
}
|
||||
|
||||
public void setSecurityMetadataSource(
|
||||
FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource) {
|
||||
this.securityMetadataSource = filterInvocationSecurityMetadataSource;
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Decides whether a web channel meets a specific security condition.
|
||||
* <p>
|
||||
* <code>ChannelProcessor</code> implementations are iterated by the
|
||||
* {@link ChannelDecisionManagerImpl}.
|
||||
* <p>
|
||||
* If an implementation has an issue with the channel security, they should take action
|
||||
* themselves. The callers of the implementation do not take any action.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated no replacement is planned, though consider using a custom
|
||||
* {@link RequestMatcher} for any sophisticated decision-making
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ChannelProcessor {
|
||||
|
||||
/**
|
||||
* Decided whether the presented {@link FilterInvocation} provides the appropriate
|
||||
* level of channel security based on the requested list of <tt>ConfigAttribute</tt>s.
|
||||
*/
|
||||
void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException;
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>ChannelProcessor</code> is able to process the passed
|
||||
* <code>ConfigAttribute</code>.
|
||||
* <p>
|
||||
* This allows the <code>ChannelProcessingFilter</code> to check every configuration
|
||||
* attribute can be consumed by the configured <code>ChannelDecisionManager</code>.
|
||||
* @param attribute a configuration attribute that has been configured against the
|
||||
* <tt>ChannelProcessingFilter</tt>.
|
||||
* @return true if this <code>ChannelProcessor</code> can support the passed
|
||||
* configuration attribute
|
||||
*/
|
||||
boolean supports(ConfigAttribute attribute);
|
||||
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Ensures channel security is inactive by review of
|
||||
* <code>HttpServletRequest.isSecure()</code> responses.
|
||||
* <p>
|
||||
* The class responds to one case-sensitive keyword, {@link #getInsecureKeyword}. If this
|
||||
* keyword is detected, <code>HttpServletRequest.isSecure()</code> is used to determine
|
||||
* the channel security offered. If channel security is present, the configured
|
||||
* <code>ChannelEntryPoint</code> is called. By default the entry point is
|
||||
* {@link RetryWithHttpEntryPoint}.
|
||||
* <p>
|
||||
* The default <code>insecureKeyword</code> is <code>REQUIRES_INSECURE_CHANNEL</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated no replacement is planned, though consider using a custom
|
||||
* {@link RequestMatcher} for any sophisticated decision-making
|
||||
*/
|
||||
@Deprecated
|
||||
public class InsecureChannelProcessor implements InitializingBean, ChannelProcessor {
|
||||
|
||||
private ChannelEntryPoint entryPoint = new RetryWithHttpEntryPoint();
|
||||
|
||||
private String insecureKeyword = "REQUIRES_INSECURE_CHANNEL";
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.hasLength(this.insecureKeyword, "insecureKeyword required");
|
||||
Assert.notNull(this.entryPoint, "entryPoint required");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
|
||||
throws IOException, ServletException {
|
||||
Assert.isTrue(invocation != null && config != null, "Nulls cannot be provided");
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (supports(attribute)) {
|
||||
if (invocation.getHttpRequest().isSecure()) {
|
||||
@Nullable HttpServletResponse response = invocation.getResponse();
|
||||
Assert.notNull(response, "HttpServletResponse required");
|
||||
this.entryPoint.commence(invocation.getRequest(), response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelEntryPoint getEntryPoint() {
|
||||
return this.entryPoint;
|
||||
}
|
||||
|
||||
public String getInsecureKeyword() {
|
||||
return this.insecureKeyword;
|
||||
}
|
||||
|
||||
public void setEntryPoint(ChannelEntryPoint entryPoint) {
|
||||
this.entryPoint = entryPoint;
|
||||
}
|
||||
|
||||
public void setInsecureKeyword(String secureKeyword) {
|
||||
this.insecureKeyword = secureKeyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return (attribute != null) && (attribute.getAttribute() != null)
|
||||
&& attribute.getAttribute().equals(getInsecureKeyword());
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.web.PortMapper;
|
||||
|
||||
/**
|
||||
* Commences an insecure channel by retrying the original request using HTTP.
|
||||
* <p>
|
||||
* This entry point should suffice in most circumstances. However, it is not intended to
|
||||
* properly handle HTTP POSTs or other usage where a standard redirect would cause an
|
||||
* issue.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated please use
|
||||
* {@link org.springframework.security.web.transport.HttpsRedirectFilter} and its
|
||||
* associated {@link PortMapper}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public class RetryWithHttpEntryPoint extends AbstractRetryEntryPoint {
|
||||
|
||||
public RetryWithHttpEntryPoint() {
|
||||
super("http://", 80);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Integer getMappedPort(Integer mapFromPort) {
|
||||
return getPortMapper().lookupHttpPort(mapFromPort);
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.web.PortMapper;
|
||||
|
||||
/**
|
||||
* Commences a secure channel by retrying the original request using HTTPS.
|
||||
* <p>
|
||||
* This entry point should suffice in most circumstances. However, it is not intended to
|
||||
* properly handle HTTP POSTs or other usage where a standard redirect would cause an
|
||||
* issue.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated please use
|
||||
* {@link org.springframework.security.web.transport.HttpsRedirectFilter} and its
|
||||
* associated {@link PortMapper}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public class RetryWithHttpsEntryPoint extends AbstractRetryEntryPoint {
|
||||
|
||||
public RetryWithHttpsEntryPoint() {
|
||||
super("https://", 443);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Integer getMappedPort(Integer mapFromPort) {
|
||||
return getPortMapper().lookupHttpsPort(mapFromPort);
|
||||
}
|
||||
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.channel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Ensures channel security is active by review of
|
||||
* <code>HttpServletRequest.isSecure()</code> responses.
|
||||
* <p>
|
||||
* The class responds to one case-sensitive keyword, {@link #getSecureKeyword}. If this
|
||||
* keyword is detected, <code>HttpServletRequest.isSecure()</code> is used to determine
|
||||
* the channel security offered. If channel security is not present, the configured
|
||||
* <code>ChannelEntryPoint</code> is called. By default the entry point is
|
||||
* {@link RetryWithHttpsEntryPoint}.
|
||||
* <p>
|
||||
* The default <code>secureKeyword</code> is <code>REQUIRES_SECURE_CHANNEL</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated no replacement is planned, though consider using a custom
|
||||
* {@link RequestMatcher} for any sophisticated decision-making
|
||||
*/
|
||||
@Deprecated
|
||||
public class SecureChannelProcessor implements InitializingBean, ChannelProcessor {
|
||||
|
||||
private ChannelEntryPoint entryPoint = new RetryWithHttpsEntryPoint();
|
||||
|
||||
private String secureKeyword = "REQUIRES_SECURE_CHANNEL";
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.hasLength(this.secureKeyword, "secureKeyword required");
|
||||
Assert.notNull(this.entryPoint, "entryPoint required");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config)
|
||||
throws IOException, ServletException {
|
||||
Assert.isTrue((invocation != null) && (config != null), "Nulls cannot be provided");
|
||||
for (ConfigAttribute attribute : config) {
|
||||
if (supports(attribute)) {
|
||||
if (!invocation.getHttpRequest().isSecure()) {
|
||||
HttpServletResponse response = invocation.getResponse();
|
||||
Assert.notNull(response, "HttpServletResponse is required");
|
||||
this.entryPoint.commence(invocation.getRequest(), response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelEntryPoint getEntryPoint() {
|
||||
return this.entryPoint;
|
||||
}
|
||||
|
||||
public String getSecureKeyword() {
|
||||
return this.secureKeyword;
|
||||
}
|
||||
|
||||
public void setEntryPoint(ChannelEntryPoint entryPoint) {
|
||||
this.entryPoint = entryPoint;
|
||||
}
|
||||
|
||||
public void setSecureKeyword(String secureKeyword) {
|
||||
this.secureKeyword = secureKeyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return (attribute != null) && (attribute.getAttribute() != null)
|
||||
&& attribute.getAttribute().equals(getSecureKeyword());
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes that ensure web requests are received over required transport channels.
|
||||
* <p>
|
||||
* Most commonly used to enforce that requests are submitted over HTTP or HTTPS.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.web.access.channel;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.web.access.expression;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.SecurityExpressionOperations;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @author Eddú Meléndez
|
||||
* @author Steve Riesenberg
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DefaultWebSecurityExpressionHandler extends AbstractSecurityExpressionHandler<FilterInvocation>
|
||||
implements SecurityExpressionHandler<FilterInvocation> {
|
||||
|
||||
private static final String DEFAULT_ROLE_PREFIX = "ROLE_";
|
||||
|
||||
private String defaultRolePrefix = DEFAULT_ROLE_PREFIX;
|
||||
|
||||
@Override
|
||||
protected SecurityExpressionOperations createSecurityExpressionRoot(@Nullable Authentication authentication,
|
||||
FilterInvocation fi) {
|
||||
FilterInvocationExpressionRoot root = new FilterInvocationExpressionRoot(() -> authentication, fi);
|
||||
root.setAuthorizationManagerFactory(getAuthorizationManagerFactory());
|
||||
root.setPermissionEvaluator(getPermissionEvaluator());
|
||||
if (!DEFAULT_ROLE_PREFIX.equals(this.defaultRolePrefix)) {
|
||||
// Ensure SecurityExpressionRoot can strip the custom role prefix
|
||||
root.setDefaultRolePrefix(this.defaultRolePrefix);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationTrustResolver} to be used. The default is
|
||||
* {@link AuthenticationTrustResolverImpl}.
|
||||
* @param trustResolver the {@link AuthenticationTrustResolver} to use. Cannot be
|
||||
* null.
|
||||
* @deprecated Use
|
||||
* {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
|
||||
getDefaultAuthorizationManagerFactory().setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Sets the default prefix to be added to
|
||||
* {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole(String...)}
|
||||
* or
|
||||
* {@link org.springframework.security.access.expression.SecurityExpressionRoot#hasRole(String)}.
|
||||
* For example, if hasRole("ADMIN") or hasRole("ROLE_ADMIN") is passed in, then the
|
||||
* role ROLE_ADMIN will be used when the defaultRolePrefix is "ROLE_" (default).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If null or empty, then no default role prefix is used.
|
||||
* </p>
|
||||
* @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
|
||||
* @deprecated Use
|
||||
* {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public void setDefaultRolePrefix(@Nullable String defaultRolePrefix) {
|
||||
if (defaultRolePrefix == null) {
|
||||
defaultRolePrefix = "";
|
||||
}
|
||||
getDefaultAuthorizationManagerFactory().setRolePrefix(defaultRolePrefix);
|
||||
this.defaultRolePrefix = defaultRolePrefix;
|
||||
}
|
||||
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.web.access.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Expression-based {@code FilterInvocationSecurityMetadataSource}.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Eddú Meléndez
|
||||
* @since 3.0
|
||||
* @deprecated In modern Spring Security APIs, each API manages its own configuration
|
||||
* context. As such there is no direct replacement for this interface. In the case of
|
||||
* method security, please see {@link SecurityAnnotationScanner} and
|
||||
* {@link AuthorizationManager}. In the case of channel security, please see
|
||||
* {@code HttpsRedirectFilter}. In the case of web security, please see
|
||||
* {@link AuthorizationManager}.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ExpressionBasedFilterInvocationSecurityMetadataSource
|
||||
extends DefaultFilterInvocationSecurityMetadataSource {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ExpressionBasedFilterInvocationSecurityMetadataSource.class);
|
||||
|
||||
public ExpressionBasedFilterInvocationSecurityMetadataSource(
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap,
|
||||
SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
super(processMap(requestMap, expressionHandler.getExpressionParser()));
|
||||
Assert.notNull(expressionHandler, "A non-null SecurityExpressionHandler is required");
|
||||
}
|
||||
|
||||
private static LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> processMap(
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap, ExpressionParser parser) {
|
||||
Assert.notNull(parser, "SecurityExpressionHandler returned a null parser object");
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> processed = new LinkedHashMap<>(requestMap);
|
||||
requestMap.forEach((request, value) -> process(parser, request, value, processed::put));
|
||||
return processed;
|
||||
}
|
||||
|
||||
private static void process(ExpressionParser parser, RequestMatcher request, Collection<ConfigAttribute> value,
|
||||
BiConsumer<RequestMatcher, Collection<ConfigAttribute>> consumer) {
|
||||
String expression = getExpression(request, value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(LogMessage.format("Adding web access control expression [%s] for %s", expression, request));
|
||||
}
|
||||
AbstractVariableEvaluationContextPostProcessor postProcessor = createPostProcessor(request);
|
||||
ArrayList<ConfigAttribute> processed = new ArrayList<>(1);
|
||||
try {
|
||||
processed.add(new WebExpressionConfigAttribute(parser.parseExpression(expression), postProcessor));
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
throw new IllegalArgumentException("Failed to parse expression '" + expression + "'");
|
||||
}
|
||||
consumer.accept(request, processed);
|
||||
}
|
||||
|
||||
private static String getExpression(RequestMatcher request, Collection<ConfigAttribute> value) {
|
||||
Assert.isTrue(value.size() == 1, () -> "Expected a single expression attribute for " + request);
|
||||
return value.toArray(new ConfigAttribute[1])[0].getAttribute();
|
||||
}
|
||||
|
||||
private static AbstractVariableEvaluationContextPostProcessor createPostProcessor(RequestMatcher request) {
|
||||
return new RequestVariablesExtractorEvaluationContextPostProcessor(request);
|
||||
}
|
||||
|
||||
static class RequestVariablesExtractorEvaluationContextPostProcessor
|
||||
extends AbstractVariableEvaluationContextPostProcessor {
|
||||
|
||||
private final RequestMatcher matcher;
|
||||
|
||||
RequestVariablesExtractorEvaluationContextPostProcessor(RequestMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<String, String> extractVariables(HttpServletRequest request) {
|
||||
return this.matcher.matcher(request).getVariables();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.web.access.expression;
|
||||
|
||||
import org.jspecify.annotations.NullUnmarked;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
|
||||
/**
|
||||
* Simple expression configuration attribute for use in web request authorizations.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
* @deprecated In modern Spring Security APIs, each API manages its own configuration
|
||||
* context. As such there is no direct replacement for this interface. Please see
|
||||
* {@link AuthorizationManager}.
|
||||
*/
|
||||
@Deprecated
|
||||
@NullUnmarked
|
||||
class WebExpressionConfigAttribute implements ConfigAttribute, EvaluationContextPostProcessor<FilterInvocation> {
|
||||
|
||||
private final Expression authorizeExpression;
|
||||
|
||||
private final EvaluationContextPostProcessor<FilterInvocation> postProcessor;
|
||||
|
||||
WebExpressionConfigAttribute(Expression authorizeExpression,
|
||||
EvaluationContextPostProcessor<FilterInvocation> postProcessor) {
|
||||
this.authorizeExpression = authorizeExpression;
|
||||
this.postProcessor = postProcessor;
|
||||
}
|
||||
|
||||
Expression getAuthorizeExpression() {
|
||||
return this.authorizeExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluationContext postProcess(EvaluationContext context, FilterInvocation fi) {
|
||||
return (this.postProcessor != null) ? this.postProcessor.postProcess(context, fi) : context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttribute() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.authorizeExpression.getExpressionString();
|
||||
}
|
||||
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* 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.web.access.expression;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.expression.ExpressionUtils;
|
||||
import org.springframework.security.access.expression.SecurityExpressionHandler;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Voter which handles web authorisation decisions.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
* @deprecated Use {@link WebExpressionAuthorizationManager} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class WebExpressionVoter implements AccessDecisionVoter<FilterInvocation> {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
|
||||
|
||||
@Override
|
||||
public int vote(Authentication authentication, FilterInvocation filterInvocation,
|
||||
Collection<ConfigAttribute> attributes) {
|
||||
Assert.notNull(authentication, "authentication must not be null");
|
||||
Assert.notNull(filterInvocation, "filterInvocation must not be null");
|
||||
Assert.notNull(attributes, "attributes must not be null");
|
||||
WebExpressionConfigAttribute webExpressionConfigAttribute = findConfigAttribute(attributes);
|
||||
if (webExpressionConfigAttribute == null) {
|
||||
this.logger
|
||||
.trace("Abstained since did not find a config attribute of instance WebExpressionConfigAttribute");
|
||||
return ACCESS_ABSTAIN;
|
||||
}
|
||||
EvaluationContext ctx = webExpressionConfigAttribute.postProcess(
|
||||
this.expressionHandler.createEvaluationContext(authentication, filterInvocation), filterInvocation);
|
||||
boolean granted = ExpressionUtils.evaluateAsBoolean(webExpressionConfigAttribute.getAuthorizeExpression(), ctx);
|
||||
if (granted) {
|
||||
return ACCESS_GRANTED;
|
||||
}
|
||||
this.logger.trace("Voted to deny authorization");
|
||||
return ACCESS_DENIED;
|
||||
}
|
||||
|
||||
private @Nullable WebExpressionConfigAttribute findConfigAttribute(Collection<ConfigAttribute> attributes) {
|
||||
for (ConfigAttribute attribute : attributes) {
|
||||
if (attribute instanceof WebExpressionConfigAttribute) {
|
||||
return (WebExpressionConfigAttribute) attribute;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return attribute instanceof WebExpressionConfigAttribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return FilterInvocation.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
public void setExpressionHandler(SecurityExpressionHandler<FilterInvocation> expressionHandler) {
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.intercept;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Default implementation of <tt>FilterInvocationDefinitionSource</tt>.
|
||||
* <p>
|
||||
* Stores an ordered map of {@link RequestMatcher}s to <tt>ConfigAttribute</tt>
|
||||
* collections and provides matching of {@code FilterInvocation}s against the items stored
|
||||
* in the map.
|
||||
* <p>
|
||||
* The order of the {@link RequestMatcher}s in the map is very important. The <b>first</b>
|
||||
* one which matches the request will be used. Later matchers in the map will not be
|
||||
* invoked if a match has already been found. Accordingly, the most specific matchers
|
||||
* should be registered first, with the most general matches registered last.
|
||||
* <p>
|
||||
* The most common method creating an instance is using the Spring Security namespace. For
|
||||
* example, the {@code pattern} and {@code access} attributes of the
|
||||
* {@code <intercept-url>} elements defined as children of the {@code <http>} element are
|
||||
* combined to build the instance used by the {@code FilterSecurityInterceptor}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @deprecated In modern Spring Security APIs, each API manages its own configuration
|
||||
* context. As such there is no direct replacement for this interface. In the case of
|
||||
* method security, please see {@link SecurityAnnotationScanner} and
|
||||
* {@link AuthorizationManager}. In the case of channel security, please see
|
||||
* {@code HttpsRedirectFilter}. In the case of web security, please see
|
||||
* {@link AuthorizationManager}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class DefaultFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Map<RequestMatcher, Collection<ConfigAttribute>> requestMap;
|
||||
|
||||
/**
|
||||
* Sets the internal request map from the supplied map. The key elements should be of
|
||||
* type {@link RequestMatcher}, which. The path stored in the key will depend on the
|
||||
* type of the supplied UrlMatcher.
|
||||
* @param requestMap order-preserving map of request definitions to attribute lists
|
||||
*/
|
||||
public DefaultFilterInvocationSecurityMetadataSource(
|
||||
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap) {
|
||||
this.requestMap = requestMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
Set<ConfigAttribute> allAttributes = new HashSet<>();
|
||||
this.requestMap.values().forEach(allAttributes::addAll);
|
||||
return allAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ConfigAttribute> getAttributes(Object object) {
|
||||
final HttpServletRequest request = getHttpServletRequest(object);
|
||||
int count = 0;
|
||||
for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : this.requestMap.entrySet()) {
|
||||
if (entry.getKey().matches(request)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
else {
|
||||
if (this.logger.isTraceEnabled()) {
|
||||
this.logger.trace(LogMessage.format("Did not match request to %s - %s (%d/%d)", entry.getKey(),
|
||||
entry.getValue(), ++count, this.requestMap.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return FilterInvocation.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
private HttpServletRequest getHttpServletRequest(Object object) {
|
||||
if (object instanceof FilterInvocation invocation) {
|
||||
return invocation.getHttpRequest();
|
||||
}
|
||||
if (object instanceof HttpServletRequest request) {
|
||||
return request;
|
||||
}
|
||||
throw new IllegalArgumentException("object must be of type FilterInvocation or HttpServletRequest");
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.intercept;
|
||||
|
||||
import org.springframework.security.access.SecurityMetadataSource;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
|
||||
/**
|
||||
* Marker interface for <code>SecurityMetadataSource</code> implementations that are
|
||||
* designed to perform lookups keyed on {@link FilterInvocation}s.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @deprecated In modern Spring Security APIs, each API manages its own configuration
|
||||
* context. As such there is no direct replacement for this interface. In the case of
|
||||
* method security, please see {@link SecurityAnnotationScanner} and
|
||||
* {@link AuthorizationManager}. In the case of channel security, please see
|
||||
* {@code HttpsRedirectFilter}. In the case of web security, please see
|
||||
* {@link AuthorizationManager}.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface FilterInvocationSecurityMetadataSource extends SecurityMetadataSource {
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.web.access.intercept;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.access.SecurityMetadataSource;
|
||||
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
|
||||
import org.springframework.security.access.intercept.InterceptorStatusToken;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
|
||||
/**
|
||||
* Performs security handling of HTTP resources via a filter implementation.
|
||||
* <p>
|
||||
* The <code>SecurityMetadataSource</code> required by this security interceptor is of
|
||||
* type {@link FilterInvocationSecurityMetadataSource}.
|
||||
* <p>
|
||||
* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Rob Winch
|
||||
* @deprecated Use {@link AuthorizationFilter} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
|
||||
|
||||
private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
|
||||
|
||||
private @Nullable FilterInvocationSecurityMetadataSource securityMetadataSource;
|
||||
|
||||
private boolean observeOncePerRequest = false;
|
||||
|
||||
/**
|
||||
* Not used (we rely on IoC container lifecycle services instead)
|
||||
* @param arg0 ignored
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void init(FilterConfig arg0) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used (we rely on IoC container lifecycle services instead)
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that is actually called by the filter chain. Simply delegates to the
|
||||
* {@link #invoke(FilterInvocation)} method.
|
||||
* @param request the servlet request
|
||||
* @param response the servlet response
|
||||
* @param chain the filter chain
|
||||
* @throws IOException if the filter chain fails
|
||||
* @throws ServletException if the filter chain fails
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
invoke(new FilterInvocation(request, response, chain));
|
||||
}
|
||||
|
||||
public @Nullable FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
|
||||
return this.securityMetadataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SecurityMetadataSource obtainSecurityMetadataSource() {
|
||||
return this.securityMetadataSource;
|
||||
}
|
||||
|
||||
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
|
||||
this.securityMetadataSource = newSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getSecureObjectClass() {
|
||||
return FilterInvocation.class;
|
||||
}
|
||||
|
||||
public void invoke(FilterInvocation filterInvocation) throws IOException, ServletException {
|
||||
if (isApplied(filterInvocation) && this.observeOncePerRequest) {
|
||||
// filter already applied to this request and user wants us to observe
|
||||
// once-per-request handling, so don't re-do security checking
|
||||
filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
|
||||
return;
|
||||
}
|
||||
// first time this request being called, so perform security checking
|
||||
if (filterInvocation.getRequest() != null && this.observeOncePerRequest) {
|
||||
filterInvocation.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
|
||||
}
|
||||
InterceptorStatusToken token = super.beforeInvocation(filterInvocation);
|
||||
try {
|
||||
filterInvocation.getChain().doFilter(filterInvocation.getRequest(), filterInvocation.getResponse());
|
||||
}
|
||||
finally {
|
||||
super.finallyInvocation(token);
|
||||
}
|
||||
super.afterInvocation(token, null);
|
||||
}
|
||||
|
||||
private boolean isApplied(FilterInvocation filterInvocation) {
|
||||
return (filterInvocation.getRequest() != null)
|
||||
&& (filterInvocation.getRequest().getAttribute(FILTER_APPLIED) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether once-per-request handling will be observed. By default this is
|
||||
* <code>true</code>, meaning the <code>FilterSecurityInterceptor</code> will only
|
||||
* execute once-per-request. Sometimes users may wish it to execute more than once per
|
||||
* request, such as when JSP forwards are being used and filter security is desired on
|
||||
* each included fragment of the HTTP request.
|
||||
* @return <code>true</code> (the default) if once-per-request is honoured, otherwise
|
||||
* <code>false</code> if <code>FilterSecurityInterceptor</code> will enforce
|
||||
* authorizations for each and every fragment of the HTTP request.
|
||||
*/
|
||||
public boolean isObserveOncePerRequest() {
|
||||
return this.observeOncePerRequest;
|
||||
}
|
||||
|
||||
public void setObserveOncePerRequest(boolean observeOncePerRequest) {
|
||||
this.observeOncePerRequest = observeOncePerRequest;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user