소스 검색

SEC-1440: Add entry-point-ref to http-basic element to allow setting a separate AuthenticationEntryPoint for the BasicAuthenticationFilter.

Luke Taylor 15 년 전
부모
커밋
57150a6717

+ 14 - 10
config/src/main/java/org/springframework/security/config/http/AuthenticationConfigBuilder.java

@@ -76,7 +76,7 @@ final class AuthenticationConfigBuilder {
     private String rememberMeServicesId;
     private BeanReference rememberMeProviderRef;
     private BeanDefinition basicFilter;
-    private BeanDefinition basicEntryPoint;
+    private RuntimeBeanReference basicEntryPoint;
     private RootBeanDefinition formFilter;
     private BeanDefinition formEntryPoint;
     private RootBeanDefinition openIDFilter;
@@ -263,25 +263,29 @@ final class AuthenticationConfigBuilder {
         }
 
         RootBeanDefinition filter = null;
-        RootBeanDefinition entryPoint = null;
 
         if (basicAuthElt != null || autoConfig) {
             BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(BasicAuthenticationFilter.class);
-            entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
-            entryPoint.setSource(pc.extractSource(httpElt));
-
-            entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
 
-            String entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
-            pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
+            String entryPointId;
+
+            if (basicAuthElt != null && StringUtils.hasText(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF))) {
+                basicEntryPoint = new RuntimeBeanReference(basicAuthElt.getAttribute(ATT_ENTRY_POINT_REF));
+            } else {
+                RootBeanDefinition entryPoint = new RootBeanDefinition(BasicAuthenticationEntryPoint.class);
+                entryPoint.setSource(pc.extractSource(httpElt));
+                entryPoint.getPropertyValues().addPropertyValue("realmName", realm);
+                entryPointId = pc.getReaderContext().generateBeanName(entryPoint);
+                pc.registerBeanComponent(new BeanComponentDefinition(entryPoint, entryPointId));
+                basicEntryPoint = new RuntimeBeanReference(entryPointId);
+            }
 
             filterBuilder.addPropertyValue("authenticationManager", authManager);
-            filterBuilder.addPropertyValue("authenticationEntryPoint", new RuntimeBeanReference(entryPointId));
+            filterBuilder.addPropertyValue("authenticationEntryPoint", basicEntryPoint);
             filter = (RootBeanDefinition) filterBuilder.getBeanDefinition();
         }
 
         basicFilter = filter;
-        basicEntryPoint = entryPoint;
     }
 
     void createX509Filter(BeanReference authManager) {

+ 7 - 4
config/src/main/resources/org/springframework/security/config/spring-security-3.1.rnc

@@ -15,7 +15,6 @@ request-matcher =
     ## Supersedes the 'path-type' attribute. Defines the strategy use for matching incoming requests. Currently the options are 'ant' (for ant path patterns), 'regex' for regular expressions and 'iciRegex' for case-insensitive regular expressions.
     attribute request-matcher {"ant" | "regex" | "ciRegex"}
 path-type =
-    ## Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.
     attribute path-type {"ant" | "regex"}
 port =
     ## Specifies an IP port number. Used to configure an embedded LDAP server, for example.
@@ -281,7 +280,7 @@ http.attlist &=
     ## Optional attribute specifying the realm name that will be used for all authentication features that require a realm name (eg BASIC and Digest authentication). If unspecified, defaults to "Spring Security Application".
     attribute realm {xsd:token}?
 http.attlist &=
-    ## Allows a customized AuthenticationEntryPoint to be used.
+    ## Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter. 
     attribute entry-point-ref {xsd:token}?
 http.attlist &=
     ## Corresponds to the observeOncePerRequest property of FilterSecurityInterceptor. Defaults to "true"
@@ -425,8 +424,12 @@ filter-invocation-definition-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}
+    ## Adds support for basic authentication
+    element http-basic {http-basic.attlist, empty}
+
+http-basic.attlist &=
+    ## Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.
+    attribute entry-point-ref {xsd:token}?
 
 session-management =
     element session-management {session-management.attlist, concurrency-control?}

+ 13 - 16
config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd

@@ -47,9 +47,6 @@
   </xs:attributeGroup>
   <xs:attributeGroup name="path-type">
     <xs:attribute name="path-type" use="required">
-      <xs:annotation>
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
-      </xs:annotation>
       <xs:simpleType>
         <xs:restriction base="xs:token">
           <xs:enumeration value="ant"/>
@@ -635,8 +632,10 @@
       <xs:attributeGroup ref="security:x509.attlist"/>
     </xs:complexType></xs:element>
         <xs:element name="http-basic"><xs:annotation>
-      <xs:documentation>Adds support for basic authentication (this is an element to permit future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
-    </xs:annotation><xs:complexType/></xs:element>
+      <xs:documentation>Adds support for basic authentication</xs:documentation>
+    </xs:annotation><xs:complexType>
+      <xs:attributeGroup ref="security:http-basic.attlist"/>
+    </xs:complexType></xs:element>
         <xs:element name="logout"><xs:annotation>
       <xs:documentation>Incorporates a logout processing filter. Most web applications require a logout filter, although you may not require one if you write a controller to provider similar logic.</xs:documentation>
     </xs:annotation><xs:complexType>
@@ -719,9 +718,6 @@
       </xs:simpleType>
     </xs:attribute>
     <xs:attribute name="path-type">
-      <xs:annotation>
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
-      </xs:annotation>
       <xs:simpleType>
         <xs:restriction base="xs:token">
           <xs:enumeration value="ant"/>
@@ -746,7 +742,7 @@
     </xs:attribute>
     <xs:attribute name="entry-point-ref" type="xs:token">
       <xs:annotation>
-        <xs:documentation>Allows a customized AuthenticationEntryPoint to be used.</xs:documentation>
+        <xs:documentation>Allows a customized AuthenticationEntryPoint to be set on the ExceptionTranslationFilter. </xs:documentation>
       </xs:annotation>
     </xs:attribute>
     <xs:attribute name="once-per-request" type="security:boolean">
@@ -924,9 +920,6 @@
     </xs:complexType></xs:element>
   <xs:attributeGroup name="filter-chain-map.attlist">
     <xs:attribute name="path-type">
-      <xs:annotation>
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
-      </xs:annotation>
       <xs:simpleType>
         <xs:restriction base="xs:token">
           <xs:enumeration value="ant"/>
@@ -981,9 +974,6 @@
       </xs:annotation>
     </xs:attribute>
     <xs:attribute name="path-type">
-      <xs:annotation>
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified.</xs:documentation>
-      </xs:annotation>
       <xs:simpleType>
         <xs:restriction base="xs:token">
           <xs:enumeration value="ant"/>
@@ -1017,6 +1007,13 @@
       <xs:attributeGroup ref="security:fsmds.attlist"/>
     </xs:complexType></xs:element>
   
+  <xs:attributeGroup name="http-basic.attlist">
+    <xs:attribute name="entry-point-ref" type="xs:token">
+      <xs:annotation>
+        <xs:documentation>Sets the AuthenticationEntryPoint which is used by the BasicAuthenticationFilter.</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:attributeGroup>
   
   <xs:attributeGroup name="session-management.attlist">
     <xs:attribute name="session-fixation-protection">
@@ -1277,7 +1274,7 @@
     </xs:attribute>
   </xs:attributeGroup>
   <xs:element name="user-service" substitutionGroup="security:any-user-service"><xs:annotation>
-      <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements.</xs:documentation>
+      <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of "user" child elements. Usernames are converted to lower-case internally to allow for case-insensitive lookups, so this should not be used if case-sensitivity is required.</xs:documentation>
     </xs:annotation><xs:complexType>
       <xs:sequence>
         <xs:element minOccurs="0" maxOccurs="unbounded" name="user"><xs:annotation>

+ 14 - 0
config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java

@@ -389,6 +389,20 @@ public class HttpSecurityBeanDefinitionParserTests {
         assertFalse(fsi.isObserveOncePerRequest());
     }
 
+    @Test
+    public void httpBasicSupportsSeparateEntryPoint() throws Exception {
+        setContext("<http><http-basic entry-point-ref='ep' /></http>" +
+                   "<b:bean id='ep' class='org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint'>" +
+                   "    <b:property name='realmName' value='whocares'/>" +
+                   "</b:bean>" + AUTH_PROVIDER_XML);
+
+        BasicAuthenticationFilter baf = getFilter(BasicAuthenticationFilter.class);
+        assertSame(appContext.getBean("ep"), FieldUtils.getFieldValue(baf, "authenticationEntryPoint"));
+        // Since no other authentication system is in use, this should also end up on the ETF
+        ExceptionTranslationFilter etf = getFilter(ExceptionTranslationFilter.class);
+        assertSame(appContext.getBean("ep"), FieldUtils.getFieldValue(etf, "authenticationEntryPoint"));
+    }
+
     @Test
     public void accessDeniedPageAttributeIsSupported() throws Exception {
         setContext("<http access-denied-page='/access-denied'><http-basic /></http>" + AUTH_PROVIDER_XML);