7 changed files with 445 additions and 120 deletions
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
package org.springframework.security.config; |
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder; |
||||
import org.springframework.beans.factory.support.RootBeanDefinition; |
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser; |
||||
import org.springframework.beans.factory.xml.ParserContext; |
||||
import org.springframework.security.ui.basicauth.BasicProcessingFilter; |
||||
import org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint; |
||||
import org.w3c.dom.Element; |
||||
|
||||
/** |
||||
* Creates a {@link BasicProcessingFilter} and {@link BasicProcessingFilterEntryPoint} and |
||||
* registers them in the application context. |
||||
* |
||||
* @author Luke Taylor |
||||
* @version $Id$ |
||||
*/ |
||||
public class BasicAuthenticationBeanDefinitionParser implements BeanDefinitionParser { |
||||
public static final String DEFAULT_BASIC_AUTH_FILTER_ID = "_basicAuthenticationFilter"; |
||||
public static final String DEFAULT_BASIC_AUTH_ENTRY_POINT_ID = "_basicAuthenticationEntryPoint"; |
||||
|
||||
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) { |
||||
BeanDefinitionBuilder filterBuilder = |
||||
BeanDefinitionBuilder.rootBeanDefinition(BasicProcessingFilter.class); |
||||
RootBeanDefinition entryPoint = new RootBeanDefinition(BasicProcessingFilterEntryPoint.class); |
||||
|
||||
String realm = elt.getAttribute("realm"); |
||||
|
||||
entryPoint.getPropertyValues().addPropertyValue("realmName", realm); |
||||
|
||||
filterBuilder.addPropertyValue("authenticationEntryPoint", entryPoint); |
||||
// Detect auth manager
|
||||
filterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); |
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(DEFAULT_BASIC_AUTH_FILTER_ID, |
||||
filterBuilder.getBeanDefinition()); |
||||
parserContext.getRegistry().registerBeanDefinition(DEFAULT_BASIC_AUTH_ENTRY_POINT_ID, entryPoint); |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
package org.springframework.security.config; |
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder; |
||||
import org.springframework.beans.factory.support.RootBeanDefinition; |
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser; |
||||
import org.springframework.beans.factory.xml.ParserContext; |
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter; |
||||
import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint; |
||||
import org.springframework.security.ui.webapp.DefaultLoginPageGeneratingFilter; |
||||
import org.springframework.util.StringUtils; |
||||
import org.w3c.dom.Element; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* @author Luke Taylor |
||||
* @version $Id$ |
||||
*/ |
||||
public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { |
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
public static final String DEFAULT_FORM_LOGIN_FILTER_ID = "_formLoginFilter"; |
||||
public static final String DEFAULT_FORM_LOGIN_ENTRY_POINT_ID = "_formLoginEntryPoint"; |
||||
|
||||
private static final String LOGIN_URL_ATTRIBUTE = "loginUrl"; |
||||
private static final String LOGIN_PAGE_ATTRIBUTE = "loginPage"; |
||||
|
||||
private static final String FORM_LOGIN_TARGET_URL_ATTRIBUTE = "defaultTargetUrl"; |
||||
private static final String DEFAULT_FORM_LOGIN_TARGET_URL = "/index"; |
||||
|
||||
private static final String FORM_LOGIN_AUTH_FAILURE_URL_ATTRIBUTE = "defaultTargetUrl"; |
||||
// TODO: Change AbstractProcessingFilter to not need a failure URL and just write a failure message
|
||||
// to the response if one isn't set.
|
||||
private static final String DEFAULT_FORM_LOGIN_AUTH_FAILURE_URL = "/loginError"; |
||||
|
||||
|
||||
public BeanDefinition parse(Element elt, ParserContext parserContext) { |
||||
BeanDefinition filterBean = createFilterBean(elt); |
||||
|
||||
BeanDefinitionBuilder entryPointBuilder = |
||||
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class); |
||||
|
||||
|
||||
String loginPage = elt.getAttribute(LOGIN_PAGE_ATTRIBUTE); |
||||
|
||||
// If no login page has been defined, add in the default page generator.
|
||||
if (!StringUtils.hasText(loginPage)) { |
||||
logger.info("No login page configured in form-login element. The default internal one will be used. Use" + |
||||
"the 'loginPage' attribute to specify the URL of the login page."); |
||||
loginPage = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL; |
||||
RootBeanDefinition loginPageFilter = new RootBeanDefinition(DefaultLoginPageGeneratingFilter.class); |
||||
loginPageFilter.getConstructorArgumentValues().addGenericArgumentValue(filterBean); |
||||
parserContext.getRegistry().registerBeanDefinition("_springSecurityLoginPageFilter", loginPageFilter); |
||||
} |
||||
|
||||
entryPointBuilder.addPropertyValue("loginFormUrl", loginPage); |
||||
|
||||
parserContext.getRegistry().registerBeanDefinition(DEFAULT_FORM_LOGIN_FILTER_ID, filterBean); |
||||
parserContext.getRegistry().registerBeanDefinition(DEFAULT_FORM_LOGIN_ENTRY_POINT_ID, |
||||
entryPointBuilder.getBeanDefinition()); |
||||
|
||||
return null; |
||||
} |
||||
|
||||
private BeanDefinition createFilterBean(Element elt) { |
||||
BeanDefinitionBuilder filterBuilder = |
||||
BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilter.class); |
||||
|
||||
String loginUrl = elt.getAttribute(LOGIN_URL_ATTRIBUTE); |
||||
|
||||
if (StringUtils.hasText(loginUrl)) { |
||||
filterBuilder.addPropertyValue("filterProcessesUrl", loginUrl); |
||||
} |
||||
|
||||
String defaultTargetUrl = elt.getAttribute(FORM_LOGIN_TARGET_URL_ATTRIBUTE); |
||||
|
||||
if (!StringUtils.hasText(defaultTargetUrl)) { |
||||
defaultTargetUrl = DEFAULT_FORM_LOGIN_TARGET_URL; |
||||
} |
||||
|
||||
filterBuilder.addPropertyValue("defaultTargetUrl", defaultTargetUrl); |
||||
|
||||
String authenticationFailureUrl = elt.getAttribute(FORM_LOGIN_AUTH_FAILURE_URL_ATTRIBUTE); |
||||
|
||||
if (!StringUtils.hasText(authenticationFailureUrl)) { |
||||
authenticationFailureUrl = DEFAULT_FORM_LOGIN_AUTH_FAILURE_URL; |
||||
} |
||||
|
||||
filterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl); |
||||
// Set autowire to pick up the authentication manager.
|
||||
filterBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); |
||||
|
||||
return filterBuilder.getBeanDefinition(); |
||||
} |
||||
} |
||||
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
package org.springframework.security.ui.webapp; |
||||
|
||||
import org.springframework.security.AuthenticationException; |
||||
import org.springframework.security.ui.AbstractProcessingFilter; |
||||
import org.springframework.security.ui.FilterChainOrderUtils; |
||||
import org.springframework.security.ui.SpringSecurityFilter; |
||||
import org.springframework.security.ui.rememberme.TokenBasedRememberMeServices; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import javax.servlet.http.HttpSession; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* For internal use with namespace configuration in the case where a user doesn't configure a login page. |
||||
* The configuration code will insert this filter in the chain instead. |
||||
* |
||||
* Will only work if a redirect is used to the login page. |
||||
* |
||||
* @author Luke Taylor |
||||
* @version $Id$ |
||||
*/ |
||||
public class DefaultLoginPageGeneratingFilter extends SpringSecurityFilter { |
||||
public static final String DEFAULT_LOGIN_PAGE_URL = "/login"; |
||||
private String authenticationUrl; |
||||
private String usernameParameter; |
||||
private String passwordParameter; |
||||
private String rememberMeParameter; |
||||
|
||||
public DefaultLoginPageGeneratingFilter(AuthenticationProcessingFilter authFilter) { |
||||
authenticationUrl = authFilter.getDefaultFilterProcessesUrl(); |
||||
usernameParameter = authFilter.getUsernameParameter(); |
||||
passwordParameter = authFilter.getPasswordParameter(); |
||||
|
||||
if (authFilter.getRememberMeServices() instanceof TokenBasedRememberMeServices) { |
||||
rememberMeParameter = ((TokenBasedRememberMeServices)authFilter.getRememberMeServices()).getParameter(); |
||||
} |
||||
} |
||||
|
||||
protected void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { |
||||
if (isLoginUrlRequest(request)) { |
||||
response.getOutputStream().print(generateLoginPageHtml(request)); |
||||
|
||||
return; |
||||
} |
||||
|
||||
chain.doFilter(request, response); |
||||
} |
||||
|
||||
private String generateLoginPageHtml(HttpServletRequest request) { |
||||
boolean loginError = StringUtils.hasText(request.getParameter("login_error")); |
||||
String errorMsg = "none"; |
||||
String lastUser = ""; |
||||
|
||||
if (loginError) { |
||||
HttpSession session = request.getSession(false); |
||||
|
||||
if(session != null) { |
||||
errorMsg = ((AuthenticationException) |
||||
session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY)).getMessage(); |
||||
} |
||||
} |
||||
|
||||
return "<html><head><title>Login Page</title></head><body>\n" + |
||||
(loginError ? ("<font color='red'>Your login attempt was not successful, try again.<br/><br/>Reason: " + |
||||
errorMsg + "</font>") : "") + |
||||
" <form action='" + request.getContextPath() + authenticationUrl + "' method='POST'>\n" + |
||||
" <table>\n" + |
||||
" <tr><td>User:</td><td><input type='text' name='" + usernameParameter + "' value='" + lastUser + |
||||
"'></td></tr>\n" + |
||||
" <tr><td>Password:</td><td><input type='password' name='"+ passwordParameter +"'></td></tr>\n" + |
||||
|
||||
(rememberMeParameter == null ? "" : |
||||
" <tr><td><input type='checkbox' name='"+ rememberMeParameter + |
||||
"'></td><td>Remember me on this computer.</td></tr>\n" |
||||
) + |
||||
" <tr><td colspan='2'><input name=\"submit\" type=\"submit\"></td></tr>\n" + |
||||
" <tr><td colspan='2'><input name=\"reset\" type=\"reset\"></td></tr>\n" + |
||||
" </table>\n" + |
||||
" </form></body></html>"; |
||||
} |
||||
|
||||
public int getOrder() { |
||||
return FilterChainOrderUtils.LOGIN_PAGE_FILTER_ORDER; |
||||
} |
||||
|
||||
private boolean isLoginUrlRequest(HttpServletRequest request) { |
||||
String uri = request.getRequestURI(); |
||||
int pathParamIndex = uri.indexOf(';'); |
||||
|
||||
if (pathParamIndex > 0) { |
||||
// strip everything after the first semi-colon
|
||||
uri = uri.substring(0, pathParamIndex); |
||||
} |
||||
|
||||
if ("".equals(request.getContextPath())) { |
||||
return uri.endsWith(DEFAULT_LOGIN_PAGE_URL); |
||||
} |
||||
|
||||
return uri.endsWith(request.getContextPath() + DEFAULT_LOGIN_PAGE_URL); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue