View Javadoc

1   package org.springframework.security.config;
2   
3   import org.springframework.beans.PropertyValue;
4   import org.springframework.beans.factory.config.BeanDefinition;
5   import org.springframework.beans.factory.config.RuntimeBeanReference;
6   import org.springframework.beans.factory.support.BeanDefinitionBuilder;
7   import org.springframework.beans.factory.support.RootBeanDefinition;
8   import org.springframework.beans.factory.xml.BeanDefinitionParser;
9   import org.springframework.beans.factory.xml.ParserContext;
10  import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint;
11  import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter;
12  import org.springframework.util.StringUtils;
13  
14  import org.w3c.dom.Element;
15  import org.apache.commons.logging.Log;
16  import org.apache.commons.logging.LogFactory;
17  
18  /**
19   * @author Luke Taylor
20   * @author Ben Alex
21   * @version $Id: FormLoginBeanDefinitionParser.java 3066 2008-05-15 01:34:14Z luke_t $
22   */
23  public class FormLoginBeanDefinitionParser implements BeanDefinitionParser {
24      protected final Log logger = LogFactory.getLog(getClass());
25  
26      static final String ATT_LOGIN_URL = "login-processing-url";
27  
28      static final String ATT_LOGIN_PAGE = "login-page";
29      static final String DEF_LOGIN_PAGE = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL;
30  
31      static final String ATT_FORM_LOGIN_TARGET_URL = "default-target-url";
32      static final String ATT_ALWAYS_USE_DEFAULT_TARGET_URL = "always-use-default-target";    
33      static final String DEF_FORM_LOGIN_TARGET_URL = "/";
34  
35      static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url";
36      static final String DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL + "?" + DefaultLoginPageGeneratingFilter.ERROR_PARAMETER_NAME;
37  
38      String defaultLoginProcessingUrl;
39      String filterClassName;
40      
41      RootBeanDefinition filterBean;
42      RootBeanDefinition entryPointBean;
43      String loginPage;
44      
45      FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName) {
46          this.defaultLoginProcessingUrl = defaultLoginProcessingUrl;
47          this.filterClassName = filterClassName;
48      }
49  
50      public BeanDefinition parse(Element elt, ParserContext pc) {
51          String loginUrl = null;
52          String defaultTargetUrl = null;
53          String authenticationFailureUrl = null;
54          String alwaysUseDefault = null;
55          
56          Object source = null;
57  
58          // Copy values from the session fixation protection filter        
59          final Boolean sessionFixationProtectionEnabled = 
60              new Boolean(pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER));
61          Boolean migrateSessionAttributes = Boolean.FALSE;
62          
63          if (sessionFixationProtectionEnabled.booleanValue()) {
64              PropertyValue pv = 
65                      pc.getRegistry().getBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER)
66                          .getPropertyValues().getPropertyValue("migrateSessionAttributes");
67              migrateSessionAttributes = (Boolean)pv.getValue(); 
68          }        
69          
70          if (elt != null) {
71              source = pc.extractSource(elt);
72              loginUrl = elt.getAttribute(ATT_LOGIN_URL);
73              ConfigUtils.validateHttpRedirect(loginUrl, pc, source);
74              defaultTargetUrl = elt.getAttribute(ATT_FORM_LOGIN_TARGET_URL);
75              ConfigUtils.validateHttpRedirect(defaultTargetUrl, pc, source);
76              authenticationFailureUrl = elt.getAttribute(ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL);
77              ConfigUtils.validateHttpRedirect(authenticationFailureUrl, pc, source);
78              alwaysUseDefault = elt.getAttribute(ATT_ALWAYS_USE_DEFAULT_TARGET_URL);
79              loginPage = elt.getAttribute(ATT_LOGIN_PAGE);
80              
81              if (!StringUtils.hasText(loginPage)) {
82                  loginPage = null;
83              }
84              ConfigUtils.validateHttpRedirect(loginPage, pc, source);
85              
86          }
87  
88          ConfigUtils.registerProviderManagerIfNecessary(pc);
89          
90          filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl);
91          filterBean.setSource(source);
92          filterBean.getPropertyValues().addPropertyValue("authenticationManager",
93                  new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
94          
95          filterBean.getPropertyValues().addPropertyValue("invalidateSessionOnSuccessfulAuthentication", 
96                  sessionFixationProtectionEnabled);
97          filterBean.getPropertyValues().addPropertyValue("migrateInvalidatedSessionAttributes", 
98                  migrateSessionAttributes);            
99          
100         if (pc.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) {
101             filterBean.getPropertyValues().addPropertyValue("rememberMeServices", 
102                     new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES) );
103         }
104         
105         if (pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_REGISTRY)) {
106             filterBean.getPropertyValues().addPropertyValue("sessionRegistry", 
107                     new RuntimeBeanReference(BeanIds.SESSION_REGISTRY));
108         }
109 
110         BeanDefinitionBuilder entryPointBuilder =
111                 BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class);
112         entryPointBuilder.setSource(source);
113         entryPointBuilder.addPropertyValue("loginFormUrl", loginPage != null ? loginPage : DEF_LOGIN_PAGE);
114         entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition();
115 
116         return null;
117     }
118 
119     private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault, 
120             String loginPage, String authenticationFailureUrl) {
121         
122         BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName);
123 
124         if (!StringUtils.hasText(loginUrl)) {
125             loginUrl = defaultLoginProcessingUrl;
126         }
127 
128         if ("true".equals(alwaysUseDefault)) {
129             filterBuilder.addPropertyValue("alwaysUseDefaultTargetUrl", Boolean.TRUE);
130         }
131         
132         filterBuilder.addPropertyValue("filterProcessesUrl", loginUrl);
133 
134         if (!StringUtils.hasText(defaultTargetUrl)) {
135             defaultTargetUrl = DEF_FORM_LOGIN_TARGET_URL;
136         }
137 
138         filterBuilder.addPropertyValue("defaultTargetUrl", defaultTargetUrl);
139 
140         if (!StringUtils.hasText(authenticationFailureUrl)) {
141             // Fallback to redisplaying the custom login page, if one was specified
142             if (StringUtils.hasText(loginPage)) {
143                 authenticationFailureUrl = loginPage;
144             } else {
145                 authenticationFailureUrl = DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL;
146             }
147         }
148 
149         filterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl);
150 
151         return (RootBeanDefinition) filterBuilder.getBeanDefinition();
152     }
153 
154     RootBeanDefinition getFilterBean() {
155         return filterBean;
156     }
157 
158     RootBeanDefinition getEntryPointBean() {
159         return entryPointBean;
160     }
161 
162     String getLoginPage() {
163         return loginPage;
164     }
165 }