SEC-1168: Added filter-security-metadat-source to namespace.
This commit is contained in:
parent
b50d37fa66
commit
66f7e8bcc8
|
@ -44,6 +44,8 @@ public abstract class Elements {
|
|||
public static final String CUSTOM_AUTH_PROVIDER = "custom-authentication-provider";
|
||||
public static final String CUSTOM_AFTER_INVOCATION_PROVIDER = "custom-after-invocation-provider";
|
||||
public static final String X509 = "x509";
|
||||
public static final String FILTER_SECURITY_METADATA_SOURCE = "filter-security-metadata-source";
|
||||
@Deprecated
|
||||
public static final String FILTER_INVOCATION_DEFINITION_SOURCE = "filter-invocation-definition-source";
|
||||
public static final String LDAP_PASSWORD_COMPARE = "password-compare";
|
||||
}
|
||||
|
|
|
@ -409,8 +409,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
|
|||
new DefaultFilterInvocationSecurityMetadataSource(matcher, channelRequestMap);
|
||||
channelFilterInvDefSource.setStripQueryStringFromUrls(matcher instanceof AntUrlPathMatcher);
|
||||
|
||||
channelFilter.getPropertyValues().addPropertyValue("filterInvocationSecurityMetadataSource",
|
||||
channelFilterInvDefSource);
|
||||
channelFilter.getPropertyValues().addPropertyValue("securityMetadataSource", channelFilterInvDefSource);
|
||||
RootBeanDefinition channelDecisionManager = new RootBeanDefinition(ChannelDecisionManagerImpl.class);
|
||||
ManagedList channelProcessors = new ManagedList(3);
|
||||
RootBeanDefinition secureChannelProcessor = new RootBeanDefinition(SecureChannelProcessor.class);
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
|||
*/
|
||||
public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void init() {
|
||||
// Parsers
|
||||
registerBeanDefinitionParser(Elements.LDAP_PROVIDER, new LdapProviderBeanDefinitionParser());
|
||||
|
@ -24,12 +25,13 @@ public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
|
|||
registerBeanDefinitionParser(Elements.GLOBAL_METHOD_SECURITY, new GlobalMethodSecurityBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.AUTHENTICATION_MANAGER, new AuthenticationManagerBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.FILTER_INVOCATION_DEFINITION_SOURCE, new FilterInvocationSecurityMetadataSourceBeanDefinitionParser());
|
||||
registerBeanDefinitionParser(Elements.FILTER_SECURITY_METADATA_SOURCE, new FilterInvocationSecurityMetadataSourceBeanDefinitionParser());
|
||||
|
||||
// Decorators
|
||||
registerBeanDefinitionDecorator(Elements.INTERCEPT_METHODS, new InterceptMethodsBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.FILTER_CHAIN_MAP, new FilterChainMapBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_FILTER, new OrderedFilterBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_AUTH_PROVIDER, new CustomAuthenticationProviderBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_AFTER_INVOCATION_PROVIDER, new CustomAfterInvocationProviderBeanDefinitionDecorator());
|
||||
registerBeanDefinitionDecorator(Elements.CUSTOM_AFTER_INVOCATION_PROVIDER, new CustomAfterInvocationProviderBeanDefinitionDecorator());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -367,20 +367,24 @@ filter-chain.attlist &=
|
|||
filter-chain.attlist &=
|
||||
attribute filters {xsd:token}
|
||||
|
||||
filter-invocation-definition-source =
|
||||
## Used to explicitly configure a FilterInvocationDefinitionSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
|
||||
element filter-invocation-definition-source {fids.attlist, intercept-url+}
|
||||
fids.attlist &=
|
||||
filter-security-metadata-source =
|
||||
## Used to explicitly configure a FilterSecurityMetadataSource bean for use with a FilterSecurityInterceptor. Usually only needed if you are configuring a FilterChainProxy explicitly, rather than using the <http> element. The intercept-url elements used should only contain pattern, method and access attributes. Any others will result in a configuration error.
|
||||
element filter-security-metadata-source {fsmds.attlist, intercept-url+}
|
||||
fsmds.attlist &=
|
||||
use-expressions?
|
||||
fids.attlist &=
|
||||
fsmds.attlist &=
|
||||
id?
|
||||
fids.attlist &=
|
||||
fsmds.attlist &=
|
||||
## as for http element
|
||||
attribute lowercase-comparisons {boolean}?
|
||||
fids.attlist &=
|
||||
fsmds.attlist &=
|
||||
## as for http element
|
||||
path-type?
|
||||
|
||||
filter-invocation-definition-source =
|
||||
## Deprecated synonym for filter-security-metadata-source
|
||||
element filter-invocation-definition-source {fsmds.attlist, intercept-url+}
|
||||
|
||||
http-basic =
|
||||
## Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)
|
||||
element http-basic {empty}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,7 @@
|
|||
<xsl:output method="xml" indent="yes"/>
|
||||
|
||||
<xsl:variable name="elts-to-inline">
|
||||
<xsl:text>,access-denied-handler,anonymous,concurrent-session-control,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,</xsl:text>
|
||||
<xsl:text>,access-denied-handler,anonymous,concurrent-session-control,user,port-mapping,openid-login,expression-handler,filter-chain,form-login,http-basic,intercept-url,logout,password-encoder,port-mappings,port-mapper,password-compare,protect,protect-pointcut,pre-post-annotation-handling,pre-invocation-advice,post-invocation-advice,invocation-attribute-factory,remember-me,salt-source,x509,</xsl:text>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:template match="xs:element">
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.w3c.dom.Element;
|
|||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
*/
|
||||
public class FilterInvocationSecurityMetadataSourceBeanDefinitionParserTests {
|
||||
public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
|
||||
private AbstractXmlApplicationContext appContext;
|
||||
|
||||
@After
|
||||
|
@ -46,9 +46,9 @@ public class FilterInvocationSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
@Test
|
||||
public void parsingMinimalConfigurationIsSuccessful() {
|
||||
setContext(
|
||||
"<filter-invocation-definition-source id='fids'>" +
|
||||
"<filter-security-metadata-source id='fids'>" +
|
||||
" <intercept-url pattern='/**' access='ROLE_A'/>" +
|
||||
"</filter-invocation-definition-source>");
|
||||
"</filter-security-metadata-source>");
|
||||
DefaultFilterInvocationSecurityMetadataSource fids = (DefaultFilterInvocationSecurityMetadataSource) appContext.getBean("fids");
|
||||
List<? extends ConfigAttribute> cad = fids.getAttributes(createFilterInvocation("/anything", "GET"));
|
||||
assertNotNull(cad);
|
||||
|
@ -61,11 +61,11 @@ public class FilterInvocationSecurityMetadataSourceBeanDefinitionParserTests {
|
|||
"<http auto-config='true'/>" +
|
||||
"<b:bean id='fsi' class='org.springframework.security.web.access.intercept.FilterSecurityInterceptor' autowire='byType'>" +
|
||||
" <b:property name='securityMetadataSource'>" +
|
||||
" <filter-invocation-definition-source>" +
|
||||
" <filter-security-metadata-source>" +
|
||||
" <intercept-url pattern='/secure/extreme/**' access='ROLE_SUPERVISOR'/>" +
|
||||
" <intercept-url pattern='/secure/**' access='ROLE_USER'/>" +
|
||||
" <intercept-url pattern='/**' access='ROLE_USER'/>" +
|
||||
" </filter-invocation-definition-source>" +
|
||||
" </filter-security-metadata-source>" +
|
||||
" </b:property>" +
|
||||
"</b:bean>" + ConfigTestUtils.AUTH_PROVIDER_XML);
|
||||
|
|
@ -16,10 +16,17 @@
|
|||
|
||||
<global-method-security run-as-manager-ref="myRunAsManager">
|
||||
<pre-post-annotation-handling>
|
||||
<
|
||||
<invocation-attribute-factory ref=""/>
|
||||
<pre-invocation-advice ref=""/>
|
||||
<post-invocation-advice ref=""/>
|
||||
</pre-post-annotation-handling>
|
||||
</global-method-security>
|
||||
|
||||
<filter-security-metadata-source>
|
||||
<intercept-url pattern=""/>
|
||||
</filter-security-metadata-source>
|
||||
|
||||
|
||||
<http>
|
||||
<access-denied-handler error-page="/go-away.html"/>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
|
|
|
@ -1,47 +1,41 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="anonymous">
|
||||
|
||||
<info><title>Anonymous Authentication</title></info>
|
||||
|
||||
|
||||
<section xml:id="anonymous-overview">
|
||||
<info><title>Overview</title></info>
|
||||
|
||||
<para>Particularly in the case of web request URI security, sometimes
|
||||
it is more convenient to assign configuration attributes against every
|
||||
possible secure object invocation. Put differently, sometimes it is
|
||||
nice to say <literal>ROLE_SOMETHING</literal> is required by default
|
||||
and only allow certain exceptions to this rule, such as for login,
|
||||
logout and home pages of an application. There are also other
|
||||
situations where anonymous authentication would be desired, such as
|
||||
when an auditing interceptor queries the
|
||||
<classname>SecurityContextHolder</classname> to identify which principal
|
||||
was responsible for a given operation. Such classes can be authored
|
||||
with more robustness if they know the
|
||||
<classname>SecurityContextHolder</classname> always contains an
|
||||
<interfacename>Authentication</interfacename> object, and never
|
||||
<literal>null</literal>.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="anonymous-config">
|
||||
<info><title>Configuration</title></info>
|
||||
|
||||
<para>Spring Security provides three classes that together provide an
|
||||
anonymous authentication feature.
|
||||
<literal>AnonymousAuthenticationToken</literal> is an implementation
|
||||
of <interfacename>Authentication</interfacename>, and stores the
|
||||
<interfacename>GrantedAuthority</interfacename>[]s which apply to the anonymous
|
||||
principal. There is a corresponding
|
||||
<literal>AnonymousAuthenticationProvider</literal>, which is chained
|
||||
into the <literal>ProviderManager</literal> so that
|
||||
<literal>AnonymousAuthenticationTokens</literal> are accepted.
|
||||
Finally, there is an AnonymousProcessingFilter, which is chained after
|
||||
the normal authentication mechanisms and automatically add an
|
||||
<literal>AnonymousAuthenticationToken</literal> to the
|
||||
<classname>SecurityContextHolder</classname> if there is no existing
|
||||
<interfacename>Authentication</interfacename> held there. The definition of the
|
||||
filter and authentication provider appears as follows:</para>
|
||||
|
||||
<para><programlisting>
|
||||
<info>
|
||||
<title>Anonymous Authentication</title>
|
||||
</info>
|
||||
<section xml:id="anonymous-overview">
|
||||
<info>
|
||||
<title>Overview</title>
|
||||
</info>
|
||||
<para>Particularly in the case of web request URI security, sometimes it is more convenient
|
||||
to assign configuration attributes against every possible secure object invocation. Put
|
||||
differently, sometimes it is nice to say <literal>ROLE_SOMETHING</literal> is required
|
||||
by default and only allow certain exceptions to this rule, such as for login, logout and
|
||||
home pages of an application. There are also other situations where anonymous
|
||||
authentication would be desired, such as when an auditing interceptor queries the
|
||||
<classname>SecurityContextHolder</classname> to identify which principal was
|
||||
responsible for a given operation. Such classes can be authored with more robustness if
|
||||
they know the <classname>SecurityContextHolder</classname> always contains an
|
||||
<interfacename>Authentication</interfacename> object, and never
|
||||
<literal>null</literal>.</para>
|
||||
</section>
|
||||
<section xml:id="anonymous-config">
|
||||
<info>
|
||||
<title>Configuration</title>
|
||||
</info>
|
||||
<para>Spring Security provides three classes that together provide an anonymous
|
||||
authentication feature. <literal>AnonymousAuthenticationToken</literal> is an
|
||||
implementation of <interfacename>Authentication</interfacename>, and stores the
|
||||
<interfacename>GrantedAuthority</interfacename>[]s which apply to the anonymous
|
||||
principal. There is a corresponding <literal>AnonymousAuthenticationProvider</literal>,
|
||||
which is chained into the <literal>ProviderManager</literal> so that
|
||||
<literal>AnonymousAuthenticationTokens</literal> are accepted. Finally, there is an
|
||||
AnonymousProcessingFilter, which is chained after the normal authentication mechanisms
|
||||
and automatically add an <literal>AnonymousAuthenticationToken</literal> to the
|
||||
<classname>SecurityContextHolder</classname> if there is no existing
|
||||
<interfacename>Authentication</interfacename> held there. The definition of the
|
||||
filter and authentication provider appears as follows:</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
<bean id="anonymousProcessingFilter"
|
||||
class="org.springframework.security.web.authentication.AnonymousProcessingFilter">
|
||||
|
@ -53,53 +47,44 @@
|
|||
class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
|
||||
<property name="key" value="foobar"/>
|
||||
</bean>]]>
|
||||
</programlisting></para>
|
||||
|
||||
<para>The <literal>key</literal> is shared between the filter and
|
||||
authentication provider, so that tokens created by the former are
|
||||
accepted by the latter. The <literal>userAttribute</literal> is
|
||||
expressed in the form of
|
||||
<literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
|
||||
This is the same syntax as used after the equals sign for
|
||||
<literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal>
|
||||
property.</para>
|
||||
|
||||
<para>As explained earlier, the benefit of anonymous authentication is
|
||||
that all URI patterns can have security applied to them. For
|
||||
example:</para>
|
||||
|
||||
<para><programlisting>
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>The <literal>key</literal> is shared between the filter and authentication provider,
|
||||
so that tokens created by the former are accepted by the latter. The
|
||||
<literal>userAttribute</literal> is expressed in the form of
|
||||
<literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
|
||||
This is the same syntax as used after the equals sign for
|
||||
<literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> property.</para>
|
||||
<para>As explained earlier, the benefit of anonymous authentication is that all URI patterns
|
||||
can have security applied to them. For example:</para>
|
||||
<para><programlisting>
|
||||
<![CDATA[
|
||||
<bean id="filterInvocationInterceptor"
|
||||
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
|
||||
<property name="objectDefinitionSource">
|
||||
<security:filter-invocation-definition-source>
|
||||
<property name="securityMetadata">
|
||||
<security:filter-security-metadata-source>
|
||||
<security:intercept-url pattern='/index.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
|
||||
<security:intercept-url pattern='/hello.htm' access='ROLE_ANONYMOUS,ROLE_USER'/>
|
||||
<security:intercept-url pattern='/logoff.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
|
||||
<security:intercept-url pattern='/login.jsp' access='ROLE_ANONYMOUS,ROLE_USER'/>
|
||||
<security:intercept-url pattern='/**' access='ROLE_USER'/>
|
||||
</security:filter-invocation-definition-source>" +
|
||||
</security:filter-security-metadata-source>" +
|
||||
</property>
|
||||
</bean>]]>
|
||||
</programlisting>Rounding out the anonymous authentication discussion
|
||||
is the <literal>AuthenticationTrustResolver</literal> interface, with
|
||||
its corresponding <literal>AuthenticationTrustResolverImpl</literal>
|
||||
implementation. This interface provides an
|
||||
<literal>isAnonymous(Authentication)</literal> method, which allows
|
||||
interested classes to take into account this special type of
|
||||
authentication status. The
|
||||
<classname>ExceptionTranslationFilter</classname> uses this interface in
|
||||
processing <literal>AccessDeniedException</literal>s. If an
|
||||
<literal>AccessDeniedException</literal> is thrown, and the
|
||||
authentication is of an anonymous type, instead of throwing a 403
|
||||
(forbidden) response, the filter will instead commence the
|
||||
<interfacename>AuthenticationEntryPoint</interfacename> so the principal can
|
||||
authenticate properly. This is a necessary distinction, otherwise
|
||||
principals would always be deemed "authenticated" and never be given
|
||||
an opportunity to login via form, basic, digest or some other normal
|
||||
authentication mechanism</para>
|
||||
</section>
|
||||
</programlisting>Rounding out the anonymous authentication discussion is the
|
||||
<literal>AuthenticationTrustResolver</literal> interface, with its corresponding
|
||||
<literal>AuthenticationTrustResolverImpl</literal> implementation. This interface
|
||||
provides an <literal>isAnonymous(Authentication)</literal> method, which allows
|
||||
interested classes to take into account this special type of authentication status. The
|
||||
<classname>ExceptionTranslationFilter</classname> uses this interface in processing
|
||||
<literal>AccessDeniedException</literal>s. If an
|
||||
<literal>AccessDeniedException</literal> is thrown, and the authentication is of an
|
||||
anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead
|
||||
commence the <interfacename>AuthenticationEntryPoint</interfacename> so the principal
|
||||
can authenticate properly. This is a necessary distinction, otherwise principals would
|
||||
always be deemed "authenticated" and never be given an opportunity to login via form,
|
||||
basic, digest or some other normal authentication mechanism</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -1,52 +1,49 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="channel-security" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<info><title>Channel Security</title></info>
|
||||
|
||||
<section xml:id="channel-security-overview">
|
||||
<info><title>Overview</title></info>
|
||||
|
||||
<para>In addition to coordinating the authentication and authorization
|
||||
requirements of your application, Spring Security is also able to
|
||||
ensure unauthenticated web requests have certain properties. These
|
||||
properties may include being of a particular transport type, having a
|
||||
particular <literal>HttpSession</literal> attribute set and so on. The
|
||||
most common requirement is for your web requests to be received using
|
||||
a particular transport protocol, such as HTTPS.</para>
|
||||
|
||||
<para>An important issue in considering transport security is that of
|
||||
session hijacking. Your web container manages a
|
||||
<literal>HttpSession</literal> by reference to a
|
||||
<literal>jsessionid</literal> that is sent to user agents either via a
|
||||
cookie or URL rewriting. If the <literal>jsessionid</literal> is ever
|
||||
sent over HTTP, there is a possibility that session identifier can be
|
||||
intercepted and used to impersonate the user after they complete the
|
||||
authentication process. This is because most web containers maintain
|
||||
the same session identifier for a given user, even after they switch
|
||||
from HTTP to HTTPS pages.</para>
|
||||
|
||||
<para>If session hijacking is considered too significant a risk for
|
||||
your particular application, the only option is to use HTTPS for every
|
||||
request. This means the <literal>jsessionid</literal> is never sent
|
||||
across an insecure channel. You will need to ensure your
|
||||
<literal>web.xml</literal>-defined
|
||||
<literal><welcome-file></literal> points to an HTTPS location,
|
||||
and the application never directs the user to an HTTP location. Spring
|
||||
Security provides a solution to assist with the latter.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="channel-security-config">
|
||||
<info><title>Configuration</title></info>
|
||||
<para>Channel security is supported by the <link xlink:href="#ns-requires-channel">security namespace</link>
|
||||
by means of the <literal>requires-channel</literal> attribute on the <literal><intercept-url></literal>
|
||||
element and this is the simplest (and recommended approach).</para>
|
||||
<para>To confiure channel security explicitly, you would define the following the filter in your application
|
||||
context:
|
||||
<programlisting><![CDATA[
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="channel-security"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>Channel Security</title>
|
||||
</info>
|
||||
<section xml:id="channel-security-overview">
|
||||
<info>
|
||||
<title>Overview</title>
|
||||
</info>
|
||||
<para>In addition to coordinating the authentication and authorization requirements of your
|
||||
application, Spring Security is also able to ensure unauthenticated web requests have
|
||||
certain properties. These properties may include being of a particular transport type,
|
||||
having a particular <literal>HttpSession</literal> attribute set and so on. The most
|
||||
common requirement is for your web requests to be received using a particular transport
|
||||
protocol, such as HTTPS.</para>
|
||||
<para>An important issue in considering transport security is that of session hijacking.
|
||||
Your web container manages a <literal>HttpSession</literal> by reference to a
|
||||
<literal>jsessionid</literal> that is sent to user agents either via a cookie or URL
|
||||
rewriting. If the <literal>jsessionid</literal> is ever sent over HTTP, there is a
|
||||
possibility that session identifier can be intercepted and used to impersonate the user
|
||||
after they complete the authentication process. This is because most web containers
|
||||
maintain the same session identifier for a given user, even after they switch from HTTP
|
||||
to HTTPS pages.</para>
|
||||
<para>If session hijacking is considered too significant a risk for your particular
|
||||
application, the only option is to use HTTPS for every request. This means the
|
||||
<literal>jsessionid</literal> is never sent across an insecure channel. You will
|
||||
need to ensure your <literal>web.xml</literal>-defined
|
||||
<literal><welcome-file></literal> points to an HTTPS location, and the
|
||||
application never directs the user to an HTTP location. Spring Security provides a
|
||||
solution to assist with the latter.</para>
|
||||
</section>
|
||||
<section xml:id="channel-security-config">
|
||||
<info>
|
||||
<title>Configuration</title>
|
||||
</info>
|
||||
<para>Channel security is supported by the <link xlink:href="#ns-requires-channel">security
|
||||
namespace</link> by means of the <literal>requires-channel</literal> attribute on
|
||||
the <literal><intercept-url></literal> element and this is the simplest (and
|
||||
recommended approach).</para>
|
||||
<para>To confiure channel security explicitly, you would define the following the filter in
|
||||
your application context: <programlisting><![CDATA[
|
||||
<bean id="channelProcessingFilter"
|
||||
class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
|
||||
<property name="channelDecisionManager" ref="channelDecisionManager"/>
|
||||
<property name="filterInvocationSecurityMetadataSource">
|
||||
<security:filter-invocation-definition-source path-type="regex">
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-security-metadata-source path-type="regex">
|
||||
<security:intercept-url pattern="\A/secure/.*\Z"
|
||||
access="REQUIRES_SECURE_CHANNEL"/>
|
||||
<security:intercept-url pattern="\A/acegilogin.jsp.*\Z"
|
||||
|
@ -54,7 +51,7 @@
|
|||
<security:intercept-url pattern="\A/j_spring_security_check.*\Z"
|
||||
access="REQUIRES_SECURE_CHANNEL"/>
|
||||
<security:intercept-url pattern="\A/.*\Z" access="ANY_CHANNEL"/>
|
||||
</security:filter-invocation-definition-source>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
@ -73,95 +70,73 @@
|
|||
<bean id="insecureChannelProcessor"
|
||||
class="org.springframework.security.access.channel.InsecureChannelProcessor"/>]]>
|
||||
</programlisting>
|
||||
Like <classname>FilterSecurityInterceptor</classname>, Apache Ant
|
||||
style paths are also supported by the
|
||||
<literal>ChannelProcessingFilter</literal>.</para>
|
||||
|
||||
<para>The <literal>ChannelProcessingFilter</literal> operates by
|
||||
filtering all web requests and determining the configuration
|
||||
attributes that apply. It then delegates to the
|
||||
<literal>ChannelDecisionManager</literal>. The default implementation,
|
||||
<literal>ChannelDecisionManagerImpl</literal>, should suffice in most
|
||||
cases. It simply delegates to the list of configured
|
||||
<literal>ChannelProcessor</literal> instances. The attribute <literal>ANY_CHANNEL</literal>
|
||||
can be used to override this behaviour and skip a particular URL. Otherwise, a
|
||||
<literal>ChannelProcessor</literal> will review the request, and if it
|
||||
is unhappy with the request (e.g. if it was received across the incorrect
|
||||
transport protocol), it will perform a redirect, throw an exception or
|
||||
take whatever other action is appropriate.</para>
|
||||
|
||||
<para>Included with Spring Security are two concrete
|
||||
<literal>ChannelProcessor</literal> implementations:
|
||||
<literal>SecureChannelProcessor</literal> ensures requests with a
|
||||
configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal>
|
||||
are received over HTTPS, whilst
|
||||
<literal>InsecureChannelProcessor</literal> ensures requests with a
|
||||
configuration attribute of
|
||||
<literal>REQUIRES_INSECURE_CHANNEL</literal> are received over HTTP.
|
||||
Both implementations delegate to a
|
||||
<literal>ChannelEntryPoint</literal> if the required transport
|
||||
protocol is not used. The two <literal>ChannelEntryPoint</literal>
|
||||
implementations included with Spring Security simply redirect the
|
||||
request to HTTP and HTTPS as appropriate. Appropriate defaults are
|
||||
assigned to the <literal>ChannelProcessor</literal> implementations
|
||||
for the configuration attribute keywords they respond to and the
|
||||
<interfacename>ChannelEntryPoint</interfacename> they delegate to, although you
|
||||
have the ability to override these using the application
|
||||
context.</para>
|
||||
|
||||
<para>Note that the redirections are absolute (eg
|
||||
<literal>http://www.company.com:8080/app/page</literal>), not relative
|
||||
(eg <literal>/app/page</literal>). During testing it was discovered
|
||||
that Internet Explorer 6 Service Pack 1 has a bug whereby it does not
|
||||
respond correctly to a redirection instruction which also changes the
|
||||
port to use. Accordingly, absolute URLs are used in conjunction with
|
||||
bug detection logic in the <classname>PortResolverImpl</classname> that is
|
||||
wired up by default to many Spring Security beans. Please refer to the
|
||||
JavaDocs for <classname>PortResolverImpl</classname> for further
|
||||
details.</para>
|
||||
|
||||
<para>You should note that using a secure channel is recommended if
|
||||
usernames and passwords are to be kept secure during the login
|
||||
process. If you do decide to use
|
||||
<classname>ChannelProcessingFilter</classname> with form-based login,
|
||||
please ensure that your login page is set to
|
||||
<literal>REQUIRES_SECURE_CHANNEL</literal>, and that the
|
||||
<literal>LoginUrlAuthenticationEntryPoint.forceHttps</literal>
|
||||
property is <literal>true</literal>.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="channel-security-conclusion">
|
||||
<info><title>Conclusion</title></info>
|
||||
|
||||
<para>Once configured, using the channel security filter is very easy.
|
||||
Simply request pages without regard to the protocol (ie HTTP or HTTPS)
|
||||
or port (eg 80, 8080, 443, 8443 etc). Obviously you'll still need a
|
||||
way of making the initial request (probably via the
|
||||
<literal>web.xml</literal> <literal><welcome-file></literal> or
|
||||
a well-known home page URL), but once this is done the filter will
|
||||
perform redirects as defined by your application context.</para>
|
||||
|
||||
<para>You can also add your own <literal>ChannelProcessor</literal>
|
||||
implementations to the <literal>ChannelDecisionManagerImpl</literal>.
|
||||
For example, you might set a <literal>HttpSession</literal> attribute
|
||||
when a human user is detected via a "enter the contents of this
|
||||
graphic" procedure. Your <literal>ChannelProcessor</literal> would
|
||||
respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration
|
||||
attributes and redirect to an appropriate entry point to start the
|
||||
human user validation process if the <literal>HttpSession</literal>
|
||||
attribute is not currently set.</para>
|
||||
|
||||
<para>To decide whether a security check belongs in a
|
||||
<literal>ChannelProcessor</literal> or an
|
||||
<interfacename>AccessDecisionVoter</interfacename>, remember that the former is
|
||||
designed to handle unauthenticated requests, whilst the latter is
|
||||
designed to handle authenticated requests. The latter therefore has
|
||||
access to the granted authorities of the authenticated principal. In
|
||||
addition, problems detected by a <literal>ChannelProcessor</literal>
|
||||
will generally cause an HTTP/HTTPS redirection so its requirements can
|
||||
be met, whilst problems detected by an
|
||||
<interfacename>AccessDecisionVoter</interfacename> will ultimately result in an
|
||||
<literal>AccessDeniedException</literal> (depending on the governing
|
||||
<interfacename>AccessDecisionManager</interfacename>).</para>
|
||||
</section>
|
||||
</chapter>
|
||||
Like <classname>FilterSecurityInterceptor</classname>, Apache Ant style paths are also
|
||||
supported by the <literal>ChannelProcessingFilter</literal>.</para>
|
||||
<para>The <literal>ChannelProcessingFilter</literal> operates by filtering all web requests
|
||||
and determining the configuration attributes that apply. It then delegates to the
|
||||
<literal>ChannelDecisionManager</literal>. The default implementation,
|
||||
<literal>ChannelDecisionManagerImpl</literal>, should suffice in most cases. It
|
||||
simply delegates to the list of configured <literal>ChannelProcessor</literal>
|
||||
instances. The attribute <literal>ANY_CHANNEL</literal> can be used to override this
|
||||
behaviour and skip a particular URL. Otherwise, a <literal>ChannelProcessor</literal>
|
||||
will review the request, and if it is unhappy with the request (e.g. if it was received
|
||||
across the incorrect transport protocol), it will perform a redirect, throw an exception
|
||||
or take whatever other action is appropriate.</para>
|
||||
<para>Included with Spring Security are two concrete <literal>ChannelProcessor</literal>
|
||||
implementations: <literal>SecureChannelProcessor</literal> ensures requests with a
|
||||
configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal> are received over
|
||||
HTTPS, whilst <literal>InsecureChannelProcessor</literal> ensures requests with a
|
||||
configuration attribute of <literal>REQUIRES_INSECURE_CHANNEL</literal> are received
|
||||
over HTTP. Both implementations delegate to a <literal>ChannelEntryPoint</literal> if
|
||||
the required transport protocol is not used. The two
|
||||
<literal>ChannelEntryPoint</literal> implementations included with Spring Security
|
||||
simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are
|
||||
assigned to the <literal>ChannelProcessor</literal> implementations for the
|
||||
configuration attribute keywords they respond to and the
|
||||
<interfacename>ChannelEntryPoint</interfacename> they delegate to, although you have
|
||||
the ability to override these using the application context.</para>
|
||||
<para>Note that the redirections are absolute (eg
|
||||
<literal>http://www.company.com:8080/app/page</literal>), not relative (eg
|
||||
<literal>/app/page</literal>). During testing it was discovered that Internet
|
||||
Explorer 6 Service Pack 1 has a bug whereby it does not respond correctly to a
|
||||
redirection instruction which also changes the port to use. Accordingly, absolute URLs
|
||||
are used in conjunction with bug detection logic in the
|
||||
<classname>PortResolverImpl</classname> that is wired up by default to many Spring
|
||||
Security beans. Please refer to the JavaDocs for <classname>PortResolverImpl</classname>
|
||||
for further details.</para>
|
||||
<para>You should note that using a secure channel is recommended if usernames and passwords
|
||||
are to be kept secure during the login process. If you do decide to use
|
||||
<classname>ChannelProcessingFilter</classname> with form-based login, please ensure
|
||||
that your login page is set to <literal>REQUIRES_SECURE_CHANNEL</literal>, and that the
|
||||
<literal>LoginUrlAuthenticationEntryPoint.forceHttps</literal> property is
|
||||
<literal>true</literal>.</para>
|
||||
</section>
|
||||
<section xml:id="channel-security-conclusion">
|
||||
<info>
|
||||
<title>Conclusion</title>
|
||||
</info>
|
||||
<para>Once configured, using the channel security filter is very easy. Simply request pages
|
||||
without regard to the protocol (ie HTTP or HTTPS) or port (eg 80, 8080, 443, 8443 etc).
|
||||
Obviously you'll still need a way of making the initial request (probably via the
|
||||
<literal>web.xml</literal>
|
||||
<literal><welcome-file></literal> or a well-known home page URL), but once this is
|
||||
done the filter will perform redirects as defined by your application context.</para>
|
||||
<para>You can also add your own <literal>ChannelProcessor</literal> implementations to the
|
||||
<literal>ChannelDecisionManagerImpl</literal>. For example, you might set a
|
||||
<literal>HttpSession</literal> attribute when a human user is detected via a "enter
|
||||
the contents of this graphic" procedure. Your <literal>ChannelProcessor</literal> would
|
||||
respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration attributes and
|
||||
redirect to an appropriate entry point to start the human user validation process if the
|
||||
<literal>HttpSession</literal> attribute is not currently set.</para>
|
||||
<para>To decide whether a security check belongs in a <literal>ChannelProcessor</literal> or
|
||||
an <interfacename>AccessDecisionVoter</interfacename>, remember that the former is
|
||||
designed to handle unauthenticated requests, whilst the latter is designed to handle
|
||||
authenticated requests. The latter therefore has access to the granted authorities of
|
||||
the authenticated principal. In addition, problems detected by a
|
||||
<literal>ChannelProcessor</literal> will generally cause an HTTP/HTTPS redirection
|
||||
so its requirements can be met, whilst problems detected by an
|
||||
<interfacename>AccessDecisionVoter</interfacename> will ultimately result in an
|
||||
<literal>AccessDeniedException</literal> (depending on the governing
|
||||
<interfacename>AccessDecisionManager</interfacename>).</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -1,36 +1,32 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="secure-object-impls" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info><title>Secure Object Implementations</title></info>
|
||||
|
||||
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="secure-object-impls"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<info>
|
||||
<title>Secure Object Implementations</title>
|
||||
</info>
|
||||
<section xml:id="aop-alliance">
|
||||
<info>
|
||||
<title>AOP Alliance (MethodInvocation) Security Interceptor</title>
|
||||
</info>
|
||||
|
||||
<para>
|
||||
Prior to Spring Security 2.0, securing <classname>MethodInvocation</classname>s needed quite a
|
||||
lot of boiler plate configuration. Now the recommended approach for method security
|
||||
is to use <link xlink:href="#ns-method-security">namespace configuration</link>.
|
||||
This way the method security infrastructure beans are configured automatically for you so you don't really need to
|
||||
know about the implementation classes. We'll just provide a quick overview of the classes that are involved here.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Method security in enforced using a <classname>MethodSecurityInterceptor</classname>, which secures
|
||||
<classname>MethodInvocation</classname>s. Depending on the configuration approach, an interceptor may be specific to a single
|
||||
bean or shared between multiple beans. The interceptor uses a <interfacename>MethodDefinitionSource</interfacename>
|
||||
instance to obtain the configuration attributes that apply to a particular method invocation.
|
||||
<classname>MapBasedMethodDefinitionSource</classname> is used to store configuration attributes keyed by method names
|
||||
(which can be wildcarded) and will be used internally when the attributes are defined in the application context using
|
||||
the <literal><intercept-methods></literal> or <literal><protect-point></literal> elements. Other implementations
|
||||
will be used to handle annotation-based configuration.
|
||||
</para>
|
||||
|
||||
<para> Prior to Spring Security 2.0, securing <classname>MethodInvocation</classname>s needed
|
||||
quite a lot of boiler plate configuration. Now the recommended approach for method security is
|
||||
to use <link xlink:href="#ns-method-security">namespace configuration</link>. This way the
|
||||
method security infrastructure beans are configured automatically for you so you don't really
|
||||
need to know about the implementation classes. We'll just provide a quick overview of the
|
||||
classes that are involved here. </para>
|
||||
<para> Method security in enforced using a <classname>MethodSecurityInterceptor</classname>,
|
||||
which secures <classname>MethodInvocation</classname>s. Depending on the configuration
|
||||
approach, an interceptor may be specific to a single bean or shared between multiple beans.
|
||||
The interceptor uses a <interfacename>MethodDefinitionSource</interfacename> instance to
|
||||
obtain the configuration attributes that apply to a particular method invocation.
|
||||
<classname>MapBasedMethodDefinitionSource</classname> is used to store configuration
|
||||
attributes keyed by method names (which can be wildcarded) and will be used internally when
|
||||
the attributes are defined in the application context using the
|
||||
<literal><intercept-methods></literal> or <literal><protect-point></literal>
|
||||
elements. Other implementations will be used to handle annotation-based configuration. </para>
|
||||
<section>
|
||||
<title>Explicit MethodSecurityIterceptor Configuration</title>
|
||||
<para>
|
||||
You can of course configure a <classname>MethodSecurityIterceptor</classname> directly in your application context
|
||||
for use with one of Spring AOP's proxying mechanisms:
|
||||
<programlisting><![CDATA[
|
||||
<para> You can of course configure a <classname>MethodSecurityIterceptor</classname> directly
|
||||
in your application context for use with one of Spring AOP's proxying mechanisms: <programlisting><![CDATA[
|
||||
<bean id="bankManagerSecurity"
|
||||
class="org.springframework.security.intercept.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
|
@ -43,37 +39,26 @@
|
|||
</value>
|
||||
</property>
|
||||
</bean> ]]>
|
||||
</programlisting>
|
||||
</para>
|
||||
</programlisting></para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="aspectj">
|
||||
<info>
|
||||
<title>AspectJ (JoinPoint) Security Interceptor</title>
|
||||
</info>
|
||||
|
||||
<para>The AspectJ security interceptor is very similar to the AOP
|
||||
Alliance security interceptor discussed in the previous section.
|
||||
Indeed we will only discuss the differences in this section.</para>
|
||||
|
||||
<para>The AspectJ interceptor is named
|
||||
<literal>AspectJSecurityInterceptor</literal>. Unlike the AOP Alliance
|
||||
security interceptor, which relies on the Spring application context
|
||||
to weave in the security interceptor via proxying, the
|
||||
<literal>AspectJSecurityInterceptor</literal> is weaved in via the
|
||||
AspectJ compiler. It would not be uncommon to use both types of
|
||||
security interceptors in the same application, with
|
||||
<literal>AspectJSecurityInterceptor</literal> being used for domain
|
||||
object instance security and the AOP Alliance
|
||||
<classname>MethodSecurityInterceptor</classname> being used for services
|
||||
layer security.</para>
|
||||
|
||||
<para>Let's first consider how the
|
||||
<literal>AspectJSecurityInterceptor</literal> is configured in the
|
||||
Spring application context:</para>
|
||||
|
||||
<para>The AspectJ security interceptor is very similar to the AOP Alliance security interceptor
|
||||
discussed in the previous section. Indeed we will only discuss the differences in this
|
||||
section.</para>
|
||||
<para>The AspectJ interceptor is named <literal>AspectJSecurityInterceptor</literal>. Unlike the
|
||||
AOP Alliance security interceptor, which relies on the Spring application context to weave in
|
||||
the security interceptor via proxying, the <literal>AspectJSecurityInterceptor</literal> is
|
||||
weaved in via the AspectJ compiler. It would not be uncommon to use both types of security
|
||||
interceptors in the same application, with <literal>AspectJSecurityInterceptor</literal> being
|
||||
used for domain object instance security and the AOP Alliance
|
||||
<classname>MethodSecurityInterceptor</classname> being used for services layer
|
||||
security.</para>
|
||||
<para>Let's first consider how the <literal>AspectJSecurityInterceptor</literal> is configured
|
||||
in the Spring application context:</para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="bankManagerSecurity"
|
||||
class="org.springframework.security.intercept.aspectj.AspectJSecurityInterceptor">
|
||||
|
@ -87,23 +72,18 @@
|
|||
</value>
|
||||
</property>
|
||||
</bean>]]> </programlisting>
|
||||
|
||||
<para>As you can see, aside from the class name, the
|
||||
<literal>AspectJSecurityInterceptor</literal> is exactly the same as
|
||||
the AOP Alliance security interceptor. Indeed the two interceptors can
|
||||
share the same <literal>securityMetadataSource</literal>, as the
|
||||
<interfacename>SecurityMetadataSource</interfacename> works with
|
||||
<literal>java.lang.reflect.Method</literal>s rather than an AOP
|
||||
library-specific class. Of course, your access decisions have access
|
||||
to the relevant AOP library-specific invocation (ie
|
||||
<classname>MethodInvocation</classname> or <literal>JoinPoint</literal>)
|
||||
and as such can consider a range of addition criteria when making
|
||||
access decisions (such as method arguments).</para>
|
||||
|
||||
<para>Next you'll need to define an AspectJ <literal>aspect</literal>.
|
||||
For example:</para>
|
||||
|
||||
<programlisting>
|
||||
<literal>AspectJSecurityInterceptor</literal> is exactly the same as the AOP Alliance
|
||||
security interceptor. Indeed the two interceptors can share the same
|
||||
<literal>securityMetadataSource</literal>, as the
|
||||
<interfacename>SecurityMetadataSource</interfacename> works with
|
||||
<literal>java.lang.reflect.Method</literal>s rather than an AOP library-specific class. Of
|
||||
course, your access decisions have access to the relevant AOP library-specific invocation (ie
|
||||
<classname>MethodInvocation</classname> or <literal>JoinPoint</literal>) and as such can
|
||||
consider a range of addition criteria when making access decisions (such as method
|
||||
arguments).</para>
|
||||
<para>Next you'll need to define an AspectJ <literal>aspect</literal>. For example:</para>
|
||||
<programlisting language="java">
|
||||
package org.springframework.security.samples.aspectj;
|
||||
|
||||
import org.springframework.security.intercept.aspectj.AspectJSecurityInterceptor;
|
||||
|
@ -144,22 +124,16 @@ public void afterPropertiesSet() throws Exception {
|
|||
throw new IllegalArgumentException("securityInterceptor required");
|
||||
}
|
||||
}</programlisting>
|
||||
|
||||
<para>In the above example, the security interceptor will be applied
|
||||
to every instance of <literal>PersistableEntity</literal>, which is an
|
||||
abstract class not shown (you can use any other class or
|
||||
<literal>pointcut</literal> expression you like). For those curious,
|
||||
<literal>AspectJCallback</literal> is needed because the
|
||||
<literal>proceed();</literal> statement has special meaning only
|
||||
within an <literal>around()</literal> body. The
|
||||
<literal>AspectJSecurityInterceptor</literal> calls this anonymous
|
||||
<literal>AspectJCallback</literal> class when it wants the target
|
||||
object to continue.</para>
|
||||
|
||||
<para>You will need to configure Spring to load the aspect and wire it
|
||||
with the <literal>AspectJSecurityInterceptor</literal>. A bean
|
||||
declaration which achieves this is shown below:</para>
|
||||
|
||||
<para>In the above example, the security interceptor will be applied to every instance of
|
||||
<literal>PersistableEntity</literal>, which is an abstract class not shown (you can use any
|
||||
other class or <literal>pointcut</literal> expression you like). For those curious,
|
||||
<literal>AspectJCallback</literal> is needed because the <literal>proceed();</literal>
|
||||
statement has special meaning only within an <literal>around()</literal> body. The
|
||||
<literal>AspectJSecurityInterceptor</literal> calls this anonymous
|
||||
<literal>AspectJCallback</literal> class when it wants the target object to continue.</para>
|
||||
<para>You will need to configure Spring to load the aspect and wire it with the
|
||||
<literal>AspectJSecurityInterceptor</literal>. A bean declaration which achieves this is
|
||||
shown below:</para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="domainObjectInstanceSecurityAspect"
|
||||
class="org.springframework.security.samples.aspectj.DomainObjectInstanceSecurityAspect"
|
||||
|
@ -167,23 +141,18 @@ public void afterPropertiesSet() throws Exception {
|
|||
<property name="securityInterceptor" ref="aspectJSecurityInterceptor"/>
|
||||
</bean>]]>
|
||||
</programlisting>
|
||||
|
||||
<para>That's it! Now you can create your beans from anywhere within
|
||||
your application, using whatever means you think fit (eg <literal>new
|
||||
Person();</literal>) and they will have the security interceptor
|
||||
applied.</para>
|
||||
<para>That's it! Now you can create your beans from anywhere within your application, using
|
||||
whatever means you think fit (eg <literal>new Person();</literal>) and they will have the
|
||||
security interceptor applied.</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="filter-invocation-authorization">
|
||||
<info><title>FilterInvocation Security Interceptor</title></info>
|
||||
|
||||
<para>To secure <classname>FilterInvocation</classname>s, developers need
|
||||
to add a <classname>FilterSecurityInterceptor</classname> to their filter chain.
|
||||
A typical configuration example is provided below:</para>
|
||||
|
||||
<para>In the application context you will need to configure three
|
||||
beans:</para>
|
||||
|
||||
<info>
|
||||
<title>FilterInvocation Security Interceptor</title>
|
||||
</info>
|
||||
<para>To secure <classname>FilterInvocation</classname>s, developers need to add a
|
||||
<classname>FilterSecurityInterceptor</classname> to their filter chain. A typical
|
||||
configuration example is provided below:</para>
|
||||
<para>In the application context you will need to configure three beans:</para>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
<bean id="exceptionTranslationFilter"
|
||||
|
@ -202,93 +171,69 @@ public void afterPropertiesSet() throws Exception {
|
|||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-invocation-definition-source>
|
||||
<security:filter-security-metadata-source>
|
||||
<security:intercept-url pattern="/secure/super/**" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="/secure/**" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-invocation-definition-source>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>]]> </programlisting>
|
||||
|
||||
<para>The <classname>ExceptionTranslationFilter</classname> provides
|
||||
the bridge between Java exceptions and HTTP responses. It is solely
|
||||
concerned with maintaining the user interface. This filter does not do
|
||||
any actual security enforcement. If an
|
||||
<exceptionname>AuthenticationException</exceptionname> is detected,
|
||||
the filter will call the AuthenticationEntryPoint to commence the
|
||||
authentication process (e.g. a user login).</para>
|
||||
|
||||
<para>The <interfacename>AuthenticationEntryPoint</interfacename> will be called
|
||||
if the user requests a secure HTTP resource but they are not
|
||||
authenticated. The class handles presenting the appropriate response
|
||||
to the user so that authentication can begin. Three concrete
|
||||
implementations are provided with Spring Security:
|
||||
<classname>LoginUrlAuthenticationEntryPoint</classname> for
|
||||
commencing a form-based authentication,
|
||||
<literal>BasicProcessingFilterEntryPoint</literal> for commencing a
|
||||
HTTP Basic authentication process, and
|
||||
<literal>CasProcessingFilterEntryPoint</literal> for commencing a
|
||||
JA-SIG Central Authentication Service (CAS) login. The
|
||||
<classname>LoginUrlAuthenticationEntryPoint</classname> and
|
||||
<literal>CasProcessingFilterEntryPoint</literal> have optional
|
||||
properties related to forcing the use of HTTPS, so please refer to the
|
||||
JavaDocs if you require this.</para>
|
||||
|
||||
<para><classname>FilterSecurityInterceptor</classname> is responsible for
|
||||
handling the security of HTTP resources. Like any other security
|
||||
interceptor, it requires a reference to an
|
||||
<interfacename>AuthenticationManager</interfacename> and an
|
||||
<interfacename>AccessDecisionManager</interfacename>, which are both discussed in
|
||||
separate sections below. The
|
||||
<classname>FilterSecurityInterceptor</classname> is also configured with
|
||||
configuration attributes that apply to different HTTP URL requests. A
|
||||
full discussion of configuration attributes is provided in the High
|
||||
Level Design section of this document.</para>
|
||||
|
||||
<para>The <classname>FilterSecurityInterceptor</classname> can be
|
||||
configured with configuration attributes in two ways. The first,
|
||||
which is shown above, is using the <literal><filter-invocation-definition-source></literal>
|
||||
namespace element. This is similar to the <literal><filter-chain-map></literal>
|
||||
used to configure a <classname>FilterChainProxy</classname> but the <literal><intercept-url></literal>
|
||||
child elements only use the <literal>pattern</literal> and <literal>access</literal> attributes.
|
||||
The second is by writing your own
|
||||
<interfacename>SecurityMetadataSource</interfacename>, although this is beyond the
|
||||
scope of this document. Irrespective of the approach used, the
|
||||
<interfacename>SecurityMetadataSource</interfacename> is responsible for returning
|
||||
a <literal>List<ConfigAttribute></literal> containing
|
||||
all of the configuration attributes associated with a single secure
|
||||
HTTP URL.</para>
|
||||
|
||||
<para>The <classname>ExceptionTranslationFilter</classname> provides the bridge between Java
|
||||
exceptions and HTTP responses. It is solely concerned with maintaining the user interface.
|
||||
This filter does not do any actual security enforcement. If an
|
||||
<exceptionname>AuthenticationException</exceptionname> is detected, the filter will call the
|
||||
AuthenticationEntryPoint to commence the authentication process (e.g. a user login).</para>
|
||||
<para>The <interfacename>AuthenticationEntryPoint</interfacename> will be called if the user
|
||||
requests a secure HTTP resource but they are not authenticated. The class handles presenting
|
||||
the appropriate response to the user so that authentication can begin. Three concrete
|
||||
implementations are provided with Spring Security:
|
||||
<classname>LoginUrlAuthenticationEntryPoint</classname> for commencing a form-based
|
||||
authentication, <literal>BasicProcessingFilterEntryPoint</literal> for commencing a HTTP Basic
|
||||
authentication process, and <literal>CasProcessingFilterEntryPoint</literal> for commencing a
|
||||
JA-SIG Central Authentication Service (CAS) login. The
|
||||
<classname>LoginUrlAuthenticationEntryPoint</classname> and
|
||||
<literal>CasProcessingFilterEntryPoint</literal> have optional properties related to forcing
|
||||
the use of HTTPS, so please refer to the JavaDocs if you require this.</para>
|
||||
<para><classname>FilterSecurityInterceptor</classname> is responsible for handling the security
|
||||
of HTTP resources. Like any other security interceptor, it requires a reference to an
|
||||
<interfacename>AuthenticationManager</interfacename> and an
|
||||
<interfacename>AccessDecisionManager</interfacename>, which are both discussed in separate
|
||||
sections below. The <classname>FilterSecurityInterceptor</classname> is also configured with
|
||||
configuration attributes that apply to different HTTP URL requests. A full discussion of
|
||||
configuration attributes is provided in the High Level Design section of this document.</para>
|
||||
<para>The <classname>FilterSecurityInterceptor</classname> can be configured with configuration
|
||||
attributes in two ways. The first, which is shown above, is using the
|
||||
<literal><filter-security-metadata-source></literal> namespace element. This is
|
||||
similar to the <literal><filter-chain-map></literal> used to configure a
|
||||
<classname>FilterChainProxy</classname> but the <literal><intercept-url></literal>
|
||||
child elements only use the <literal>pattern</literal> and <literal>access</literal>
|
||||
attributes. The second is by writing your own
|
||||
<interfacename>SecurityMetadataSource</interfacename>, although this is beyond the scope of
|
||||
this document. Irrespective of the approach used, the
|
||||
<interfacename>SecurityMetadataSource</interfacename> is responsible for returning a
|
||||
<literal>List<ConfigAttribute></literal> containing all of the configuration
|
||||
attributes associated with a single secure HTTP URL.</para>
|
||||
<para>It should be noted that the
|
||||
<literal>FilterSecurityInterceptor.setSecurityMetadataSource()</literal>
|
||||
method actually expects an instance of
|
||||
<interfacename>FilterInvocationDefinitionSource</interfacename>. This is a marker
|
||||
interface which subclasses <interfacename>SecurityMetadataSource</interfacename>.
|
||||
It simply denotes the <interfacename>SecurityMetadataSource</interfacename>
|
||||
understands <classname>FilterInvocation</classname>s. In the interests of
|
||||
simplicity we'll continue to refer to the
|
||||
<interfacename>FilterInvocationDefinitionSource</interfacename> as an
|
||||
<interfacename>SecurityMetadataSource</interfacename>, as the distinction is of
|
||||
little relevance to most users of the
|
||||
<classname>FilterSecurityInterceptor</classname>.</para>
|
||||
|
||||
<para>When using the namespace option to configure the interceptor,
|
||||
commas are used to delimit the different configuration
|
||||
attributes that apply to each HTTP URL. Each configuration attribute
|
||||
is assigned into its own <literal>SecurityConfig</literal> object. The
|
||||
<literal>SecurityConfig</literal> object is discussed in the High
|
||||
Level Design section. The <interfacename>SecurityMetadataSource</interfacename>
|
||||
created by the property editor,
|
||||
<interfacename>FilterInvocationDefinitionSource</interfacename>, matches
|
||||
configuration attributes against <literal>FilterInvocations</literal>
|
||||
based on expression evaluation of the request URL. Two standard
|
||||
expression syntaxes are supported. The default is to treat all
|
||||
expressions as Apache Ant paths and regular expressions are also supported
|
||||
for ore complex cases. The <literal>path-type</literal> attribute is used
|
||||
to specify the type of pattern being used. It is not possible to
|
||||
mix expression syntaxes within the same definition. For example, the
|
||||
previous configuration using regular expressions instead of Ant paths would be
|
||||
written as follows:</para>
|
||||
|
||||
<literal>FilterSecurityInterceptor.setSecurityMetadataSource()</literal> method actually
|
||||
expects an instance of <interfacename>FilterInvocationDefinitionSource</interfacename>. This
|
||||
is a marker interface which subclasses <interfacename>SecurityMetadataSource</interfacename>.
|
||||
It simply denotes the <interfacename>SecurityMetadataSource</interfacename> understands
|
||||
<classname>FilterInvocation</classname>s. In the interests of simplicity we'll continue to
|
||||
refer to the <interfacename>FilterInvocationDefinitionSource</interfacename> as an
|
||||
<interfacename>SecurityMetadataSource</interfacename>, as the distinction is of little
|
||||
relevance to most users of the <classname>FilterSecurityInterceptor</classname>.</para>
|
||||
<para>When using the namespace option to configure the interceptor, commas are used to delimit
|
||||
the different configuration attributes that apply to each HTTP URL. Each configuration
|
||||
attribute is assigned into its own <literal>SecurityConfig</literal> object. The
|
||||
<literal>SecurityConfig</literal> object is discussed in the High Level Design section. The
|
||||
<interfacename>SecurityMetadataSource</interfacename> created by the property editor,
|
||||
<interfacename>FilterInvocationDefinitionSource</interfacename>, matches configuration
|
||||
attributes against <literal>FilterInvocations</literal> based on expression evaluation of the
|
||||
request URL. Two standard expression syntaxes are supported. The default is to treat all
|
||||
expressions as Apache Ant paths and regular expressions are also supported for ore complex
|
||||
cases. The <literal>path-type</literal> attribute is used to specify the type of pattern being
|
||||
used. It is not possible to mix expression syntaxes within the same definition. For example,
|
||||
the previous configuration using regular expressions instead of Ant paths would be written as
|
||||
follows:</para>
|
||||
<programlisting><![CDATA[
|
||||
<bean id="filterInvocationInterceptor"
|
||||
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
|
||||
|
@ -296,32 +241,25 @@ public void afterPropertiesSet() throws Exception {
|
|||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="runAsManager" ref="runAsManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<security:filter-invocation-definition-source path-type="regex">
|
||||
<security:filter-security-metadata-source path-type="regex">
|
||||
<security:intercept-url pattern="\A/secure/super/.*\Z" access="ROLE_WE_DONT_HAVE"/>
|
||||
<security:intercept-url pattern="\A/secure/.*\" access="ROLE_SUPERVISOR,ROLE_TELLER"/>
|
||||
</security:filter-invocation-definition-source>
|
||||
</security:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>]]> </programlisting>
|
||||
|
||||
<para>Irrespective of the type of expression syntax used, expressions
|
||||
are always evaluated in the order they are defined. Thus it is
|
||||
important that more specific expressions are defined higher in the
|
||||
list than less specific expressions. This is reflected in our example
|
||||
above, where the more specific <literal>/secure/super/</literal>
|
||||
pattern appears higher than the less specific
|
||||
<literal>/secure/</literal> pattern. If they were reversed, the
|
||||
<literal>/secure/</literal> pattern would always match and the
|
||||
<literal>/secure/super/</literal> pattern would never be
|
||||
evaluated.</para>
|
||||
|
||||
<para>As with other security interceptors, the
|
||||
<literal>validateConfigAttributes</literal> property is observed. When
|
||||
set to <literal>true</literal> (the default), at startup time the
|
||||
<classname>FilterSecurityInterceptor</classname> will evaluate if the
|
||||
provided configuration attributes are valid. It does this by checking
|
||||
each configuration attribute can be processed by either the
|
||||
<interfacename>AccessDecisionManager</interfacename> or the
|
||||
<literal>RunAsManager</literal>. If neither of these can process a
|
||||
given configuration attribute, an exception is thrown.</para>
|
||||
<para>Irrespective of the type of expression syntax used, expressions are always evaluated in
|
||||
the order they are defined. Thus it is important that more specific expressions are defined
|
||||
higher in the list than less specific expressions. This is reflected in our example above,
|
||||
where the more specific <literal>/secure/super/</literal> pattern appears higher than the less
|
||||
specific <literal>/secure/</literal> pattern. If they were reversed, the
|
||||
<literal>/secure/</literal> pattern would always match and the
|
||||
<literal>/secure/super/</literal> pattern would never be evaluated.</para>
|
||||
<para>As with other security interceptors, the <literal>validateConfigAttributes</literal>
|
||||
property is observed. When set to <literal>true</literal> (the default), at startup time the
|
||||
<classname>FilterSecurityInterceptor</classname> will evaluate if the provided configuration
|
||||
attributes are valid. It does this by checking each configuration attribute can be processed
|
||||
by either the <interfacename>AccessDecisionManager</interfacename> or the
|
||||
<literal>RunAsManager</literal>. If neither of these can process a given configuration
|
||||
attribute, an exception is thrown.</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -92,11 +92,11 @@
|
|||
<property name="authenticationManager" ref="authenticationManager"/>
|
||||
<property name="accessDecisionManager" ref="accessDecisionManager"/>
|
||||
<property name="securityMetadataSource">
|
||||
<sec:filter-invocation-definition-source>
|
||||
<sec:filter-security-metadata-source>
|
||||
<sec:intercept-url pattern="/secure/extreme/**" access="ROLE_2"/>
|
||||
<sec:intercept-url pattern="/secure/**" access="ROLE_1"/>
|
||||
<sec:intercept-url pattern="/**" access="ROLE_0"/>
|
||||
</sec:filter-invocation-definition-source>
|
||||
</sec:filter-security-metadata-source>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
|
|
@ -51,15 +51,15 @@ public class ChannelProcessingFilter extends SpringSecurityFilter implements Ini
|
|||
//~ Instance fields ================================================================================================
|
||||
|
||||
private ChannelDecisionManager channelDecisionManager;
|
||||
private FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource;
|
||||
private FilterInvocationSecurityMetadataSource securityMetadataSource;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(filterInvocationSecurityMetadataSource, "filterInvocationSecurityMetadataSource must be specified");
|
||||
Assert.notNull(securityMetadataSource, "securityMetadataSource must be specified");
|
||||
Assert.notNull(channelDecisionManager, "channelDecisionManager must be specified");
|
||||
|
||||
Collection<ConfigAttribute> attrDefs = this.filterInvocationSecurityMetadataSource.getAllConfigAttributes();
|
||||
Collection<ConfigAttribute> attrDefs = this.securityMetadataSource.getAllConfigAttributes();
|
||||
|
||||
if (attrDefs == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
|
@ -91,7 +91,7 @@ public class ChannelProcessingFilter extends SpringSecurityFilter implements Ini
|
|||
throws IOException, ServletException {
|
||||
|
||||
FilterInvocation fi = new FilterInvocation(request, response, chain);
|
||||
List<ConfigAttribute> attr = this.filterInvocationSecurityMetadataSource.getAttributes(fi);
|
||||
List<ConfigAttribute> attr = this.securityMetadataSource.getAttributes(fi);
|
||||
|
||||
if (attr != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
@ -112,16 +112,16 @@ public class ChannelProcessingFilter extends SpringSecurityFilter implements Ini
|
|||
return channelDecisionManager;
|
||||
}
|
||||
|
||||
public FilterInvocationSecurityMetadataSource getFilterInvocationSecurityMetadataSource() {
|
||||
return filterInvocationSecurityMetadataSource;
|
||||
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
|
||||
return securityMetadataSource;
|
||||
}
|
||||
|
||||
public void setChannelDecisionManager(ChannelDecisionManager channelDecisionManager) {
|
||||
this.channelDecisionManager = channelDecisionManager;
|
||||
}
|
||||
|
||||
public void setFilterInvocationSecurityMetadataSource(FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource) {
|
||||
this.filterInvocationSecurityMetadataSource = filterInvocationSecurityMetadataSource;
|
||||
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource) {
|
||||
this.securityMetadataSource = filterInvocationSecurityMetadataSource;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
package org.springframework.security.web.access.channel;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -31,8 +31,6 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.channel.ChannelDecisionManager;
|
||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
|
||||
|
||||
|
@ -50,7 +48,7 @@ public class ChannelProcessingFilterTests {
|
|||
ChannelProcessingFilter filter = new ChannelProcessingFilter();
|
||||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "MOCK");
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
@ -69,7 +67,7 @@ public class ChannelProcessingFilterTests {
|
|||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SUPPORTS_MOCK_ONLY");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
@ -81,7 +79,7 @@ public class ChannelProcessingFilterTests {
|
|||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SUPPORTS_MOCK_ONLY", "INVALID_ATTRIBUTE");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
@ -92,7 +90,7 @@ public class ChannelProcessingFilterTests {
|
|||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=now");
|
||||
|
@ -110,7 +108,7 @@ public class ChannelProcessingFilterTests {
|
|||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "SOME_ATTRIBUTE");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=now");
|
||||
|
@ -129,7 +127,7 @@ public class ChannelProcessingFilterTests {
|
|||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", true, "NOT_USED");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("info=now");
|
||||
|
@ -148,8 +146,8 @@ public class ChannelProcessingFilterTests {
|
|||
|
||||
MockFilterInvocationDefinitionMap fids = new MockFilterInvocationDefinitionMap("/path", false, "MOCK");
|
||||
|
||||
filter.setFilterInvocationSecurityMetadataSource(fids);
|
||||
assertTrue(filter.getFilterInvocationSecurityMetadataSource() != null);
|
||||
filter.setSecurityMetadataSource(fids);
|
||||
assertSame(fids, filter.getSecurityMetadataSource());
|
||||
|
||||
filter.init(null);
|
||||
filter.afterPropertiesSet();
|
||||
|
|
Loading…
Reference in New Issue