mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-03-03 20:09:18 +00:00
SEC-746: impossible to specify errorPage for the AccessDeniedHandlerImp when using namespace based configuration
http://jira.springframework.org/browse/SEC-746. Added access-denied-page to http element.
This commit is contained in:
parent
f57ba43780
commit
243b5f4a2a
@ -17,6 +17,7 @@ package org.springframework.security.util;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@ -56,8 +57,7 @@ public final class FieldUtils {
|
||||
*
|
||||
* @throws IllegalStateException if field could not be found
|
||||
*/
|
||||
public static Field getField(Class clazz, String fieldName)
|
||||
throws IllegalStateException {
|
||||
public static Field getField(Class clazz, String fieldName) throws IllegalStateException {
|
||||
Assert.notNull(clazz, "Class required");
|
||||
Assert.hasText(fieldName, "Field name required");
|
||||
|
||||
@ -72,6 +72,31 @@ public final class FieldUtils {
|
||||
throw new IllegalStateException("Could not locate field '" + fieldName + "' on class " + clazz);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a (nested) field on a bean. Intended for testing.
|
||||
* @param bean the object
|
||||
* @param fieldName the field name, with "." separating nested properties
|
||||
* @return the value of the nested field
|
||||
*/
|
||||
public static Object getFieldValue(Object bean, String fieldName) throws IllegalAccessException {
|
||||
Assert.notNull(bean, "Bean cannot be null");
|
||||
Assert.hasText(fieldName, "Field name required");
|
||||
String[] nestedFields = StringUtils.tokenizeToStringArray(fieldName, ".");
|
||||
Class componentClass = bean.getClass();
|
||||
Field field = null;
|
||||
Object value = bean;
|
||||
|
||||
for (int i=0; i < nestedFields.length; i++) {
|
||||
field = getField(componentClass, nestedFields[i]);
|
||||
field.setAccessible(true);
|
||||
value = field.get(value);
|
||||
componentClass = value.getClass();
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
public static String getMutatorName(String fieldName) {
|
||||
Assert.hasText(fieldName, "FieldName required");
|
||||
|
@ -1,12 +1,9 @@
|
||||
|
||||
namespace beans = "http://www.springframework.org/schema/beans"
|
||||
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
|
||||
namespace security = "http://www.springframework.org/schema/security"
|
||||
datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
|
||||
|
||||
default namespace = "http://www.springframework.org/schema/security"
|
||||
|
||||
start = http | ldap-server | authentication-provider | ldap-authentication-provider | user-service
|
||||
start = http | ldap-server | authentication-provider | ldap-authentication-provider | any-user-service | ldap-server | ldap-authentication-provider
|
||||
|
||||
hash =
|
||||
## Defines the hashing algorithm used on user passwords. We recommend strongly against using MD4, as it is a very weak hashing algorithm.
|
||||
@ -52,6 +49,8 @@ user-property =
|
||||
system-wide =
|
||||
## A single value that will be used as the salt for a password encoder.
|
||||
attribute system-wide {xsd:string}
|
||||
|
||||
boolean = "true" | "false"
|
||||
|
||||
|
||||
ldap-server =
|
||||
@ -189,7 +188,7 @@ http =
|
||||
element http {http.attlist, (intercept-url+ & form-login? & openid-login & x509? & http-basic? & logout? & concurrent-session-control? & remember-me? & anonymous? & port-mappings) }
|
||||
http.attlist &=
|
||||
## Automatically registers a login form, BASIC authentication, anonymous authentication, logout services, remember-me and servlet-api-integration. If set to "true", all of these capabilities are added (although you can still customize the configuration of each by providing the respective element). If unspecified, defaults to "false".
|
||||
attribute auto-config {"true" | "false" }?
|
||||
attribute auto-config {boolean}?
|
||||
http.attlist &=
|
||||
## Controls the eagerness with which an HTTP session is created. If not set, defaults to "ifRequired".
|
||||
attribute create-session {"ifRequired" | "always" | "never" }?
|
||||
@ -198,10 +197,10 @@ http.attlist &=
|
||||
path-type?
|
||||
http.attlist &=
|
||||
## Whether test URLs should be converted to lower case prior to comparing with defined path patterns. If unspecified, defaults to "true".
|
||||
attribute lowercase-comparisons {"true" | "false"}?
|
||||
attribute lowercase-comparisons {boolean}?
|
||||
http.attlist &=
|
||||
## Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by accessing the Spring SecurityContext. Defaults to "true".
|
||||
attribute servlet-api-provision {"true" | "false"}?
|
||||
attribute servlet-api-provision {boolean}?
|
||||
http.attlist &=
|
||||
## Optional attribute specifying the ID of the AccessDecisionManager implementation which should be used for authorizing HTTP requests.
|
||||
attribute access-decision-manager-ref {xsd:string}?
|
||||
@ -216,8 +215,10 @@ http.attlist &=
|
||||
attribute entry-point-ref {xsd:string}?
|
||||
http.attlist &=
|
||||
## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "false"
|
||||
attribute once-per-request {"true" | "false"}?
|
||||
|
||||
attribute once-per-request {boolean}?
|
||||
http.attlist &=
|
||||
## Allows the access denied page to be set (the user will be redirected here if an AccessDeniedException is raised).
|
||||
attribute access-denied-page {xsd:string}?
|
||||
|
||||
intercept-url =
|
||||
## Specifies the access attributes and/or filter list for a particular set of URLs.
|
||||
@ -250,7 +251,7 @@ logout.attlist &=
|
||||
attribute logout-success-url {xsd:string}?
|
||||
logout.attlist &=
|
||||
## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.
|
||||
attribute invalidate-session {"true" | "false"}?
|
||||
attribute invalidate-session {boolean}?
|
||||
|
||||
form-login =
|
||||
## Sets up a form login configuration for authentication with a username and password
|
||||
@ -294,7 +295,7 @@ fids.attlist &=
|
||||
id?
|
||||
fids.attlist &=
|
||||
## as for http element
|
||||
attribute lowercase-comparisons {"true" | "false"}?
|
||||
attribute lowercase-comparisons {boolean}?
|
||||
fids.attlist &=
|
||||
## as for http element
|
||||
path-type?
|
||||
@ -312,7 +313,7 @@ concurrent-sessions.attlist &=
|
||||
concurrent-sessions.attlist &=
|
||||
attribute expired-url {xsd:string}?
|
||||
concurrent-sessions.attlist &=
|
||||
attribute exception-if-maximum-exceeded {"true" | "false"}?
|
||||
attribute exception-if-maximum-exceeded {boolean}?
|
||||
concurrent-sessions.attlist &=
|
||||
## Allows you to define an alias for the SessionRegistry bean in order to access it in your own configuration
|
||||
attribute session-registry-alias {xsd:string}?
|
||||
@ -400,7 +401,7 @@ user.attlist &=
|
||||
attribute authorities {xsd:string}
|
||||
user.attlist &=
|
||||
## Can be set to "true" to mark an account as locked and unusable.
|
||||
attribute locked {"true" | "false"}?
|
||||
attribute locked {boolean}?
|
||||
|
||||
|
||||
jdbc-user-service =
|
||||
|
@ -144,6 +144,12 @@
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:simpleType name="boolean">
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:element name="ldap-server">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines an LDAP server location or starts an embedded server. The url
|
||||
@ -609,7 +615,7 @@
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:attributeGroup name="http.attlist">
|
||||
<xs:attribute name="auto-config">
|
||||
<xs:attribute name="auto-config" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Automatically registers a login form, BASIC authentication, anonymous
|
||||
authentication, logout services, remember-me and servlet-api-integration. If set to
|
||||
@ -617,12 +623,6 @@
|
||||
configuration of each by providing the respective element). If unspecified, defaults to
|
||||
"false".</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="create-session">
|
||||
<xs:annotation>
|
||||
@ -650,30 +650,18 @@
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lowercase-comparisons">
|
||||
<xs:attribute name="lowercase-comparisons" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Whether test URLs should be converted to lower case prior to comparing
|
||||
with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="servlet-api-provision">
|
||||
<xs:attribute name="servlet-api-provision" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Provides versions of HttpServletRequest security methods such as
|
||||
isUserInRole() and getPrincipal() which are implemented by accessing the Spring
|
||||
SecurityContext. Defaults to "true".</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="access-decision-manager-ref" type="xs:string">
|
||||
<xs:annotation>
|
||||
@ -710,17 +698,17 @@
|
||||
used.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="once-per-request">
|
||||
<xs:attribute name="once-per-request" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Corresponds to the observeOncePerRequest property of
|
||||
FilterSecurityInterceptor. Defaults to "false"</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="access-denied-page" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Allows the access denied page to be set (the user will be redirected here
|
||||
if an AccessDeniedException is raised).</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:attributeGroup name="intercept-url.attlist">
|
||||
@ -794,17 +782,11 @@
|
||||
specified, defaults to /.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="invalidate-session">
|
||||
<xs:attribute name="invalidate-session" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is
|
||||
generally desirable. If unspecified, defaults to true.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:attributeGroup name="form-login.attlist">
|
||||
@ -914,16 +896,10 @@
|
||||
context.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lowercase-comparisons">
|
||||
<xs:attribute name="lowercase-comparisons" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>as for http element</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="path-type">
|
||||
<xs:annotation>
|
||||
@ -942,14 +918,7 @@
|
||||
<xs:attributeGroup name="concurrent-sessions.attlist">
|
||||
<xs:attribute name="max-sessions" type="xs:positiveInteger"/>
|
||||
<xs:attribute name="expired-url" type="xs:string"/>
|
||||
<xs:attribute name="exception-if-maximum-exceeded">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="exception-if-maximum-exceeded" type="security:boolean"/>
|
||||
<xs:attribute name="session-registry-alias" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Allows you to define an alias for the SessionRegistry bean in order to
|
||||
@ -1136,17 +1105,11 @@
|
||||
comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="locked">
|
||||
<xs:attribute name="locked" type="security:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Can be set to "true" to mark an account as locked and
|
||||
unusable.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="true"/>
|
||||
<xs:enumeration value="false"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
|
||||
|
@ -1,10 +1,6 @@
|
||||
package org.springframework.security.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -35,11 +31,11 @@ import org.springframework.security.ui.WebAuthenticationDetails;
|
||||
import org.springframework.security.ui.basicauth.BasicProcessingFilter;
|
||||
import org.springframework.security.ui.logout.LogoutFilter;
|
||||
import org.springframework.security.ui.preauth.x509.X509PreAuthenticatedProcessingFilter;
|
||||
import org.springframework.security.ui.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.security.ui.rememberme.PersistentTokenBasedRememberMeServices;
|
||||
import org.springframework.security.ui.rememberme.RememberMeProcessingFilter;
|
||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
|
||||
import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.util.FilterChainProxy;
|
||||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.util.PortMapperImpl;
|
||||
@ -198,6 +194,17 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) filters.get(filters.size() - 1);
|
||||
|
||||
assertTrue(fsi.isObserveOncePerRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessDeniedPageAttributeIsSupported() throws Exception {
|
||||
setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);
|
||||
FilterChainProxy filterChainProxy = getFilterChainProxy();
|
||||
List filters = filterChainProxy.getFilters("/someurl");
|
||||
|
||||
ExceptionTranslationFilter etf = (ExceptionTranslationFilter) filters.get(filters.size() - 2);
|
||||
|
||||
assertEquals("/access-denied", FieldUtils.getFieldValue(etf, "accessDeniedHandler.errorPage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -376,7 +383,6 @@ public class HttpSecurityBeanDefinitionParserTests {
|
||||
assertEquals("Hello from the post processor!", service.getPostProcessorWasHere());
|
||||
}
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appContext = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user