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
20
21
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
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
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 }