소스 검색

SEC-2359: Merge DefaultLoginPageViewFilter w/ DefaultLoginPageGeneratingFilter

Rob Winch 12 년 전
부모
커밋
0b0e7dbea9

+ 1 - 1
config/src/main/java/org/springframework/security/config/annotation/web/HttpSecurityBuilder.java

@@ -152,7 +152,7 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends S
      * <li>{@link UsernamePasswordAuthenticationFilter}</li>
      * <li>{@link ConcurrentSessionFilter}</li>
      * <li>{@link OpenIDAuthenticationFilter}</li>
-     * <li>{@link DefaultLoginPageViewFilter}</li>
+     * <li>{@link DefaultLoginPageGeneratingFilter}</li>
      * <li>{@link ConcurrentSessionFilter}</li>
      * <li>{@link DigestAuthenticationFilter}</li>
      * <li>{@link BasicAuthenticationFilter}</li>

+ 2 - 2
config/src/main/java/org/springframework/security/config/annotation/web/builders/FilterComparator.java

@@ -32,7 +32,7 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen
 import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
 import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
 import org.springframework.security.web.authentication.switchuser.SwitchUserFilter;
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
 import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;
 import org.springframework.security.web.context.SecurityContextPersistenceFilter;
@@ -86,7 +86,7 @@ final class FilterComparator implements Comparator<Filter>, Serializable {
         order += STEP;
         filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order);
         order += STEP;
-        put(DefaultLoginPageViewFilter.class, order);
+        put(DefaultLoginPageGeneratingFilter.class, order);
         order += STEP;
         put(ConcurrentSessionFilter.class, order);
         order += STEP;

+ 4 - 4
config/src/main/java/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurer.java

@@ -18,7 +18,7 @@ package org.springframework.security.config.annotation.web.configurers;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 
 /**
  * Adds a Filter that will generate a login page if one is not specified otherwise when using {@link WebSecurityConfigurerAdapter}.
@@ -32,7 +32,7 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFi
  * The following Filters are conditionally populated
  *
  * <ul>
- *     <li>{@link DefaultLoginPageViewFilter} if the {@link FormLoginConfigurer} did not have a login page specified</li>
+ *     <li>{@link DefaultLoginPageGeneratingFilter} if the {@link FormLoginConfigurer} did not have a login page specified</li>
  * </ul>
  *
  * <h2>Shared Objects Created</h2>
@@ -56,11 +56,11 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFi
 public final class DefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>> extends
         AbstractHttpConfigurer<DefaultLoginPageConfigurer<H>,H> {
 
-    private DefaultLoginPageViewFilter loginPageGeneratingFilter = new DefaultLoginPageViewFilter();
+    private DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = new DefaultLoginPageGeneratingFilter();
 
     @Override
     public void init(H http) throws Exception {
-        http.setSharedObject(DefaultLoginPageViewFilter.class, loginPageGeneratingFilter);
+        http.setSharedObject(DefaultLoginPageGeneratingFilter.class, loginPageGeneratingFilter);
     }
 
     @Override

+ 4 - 4
config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java

@@ -22,7 +22,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.security.web.authentication.RememberMeServices;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 
@@ -57,7 +57,7 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
  * <li>{@link AuthenticationManager}</li>
  * <li>{@link RememberMeServices} - is optionally used. See {@link RememberMeConfigurer}</li>
  * <li>{@link SessionAuthenticationStrategy} - is optionally used. See {@link SessionManagementConfigurer}</li>
- * <li>{@link DefaultLoginPageViewFilter} - if present will be populated with information from the configuration</li>
+ * <li>{@link DefaultLoginPageGeneratingFilter} - if present will be populated with information from the configuration</li>
  * </ul>
  *
  * @author Rob Winch
@@ -245,12 +245,12 @@ public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
     }
 
     /**
-     * If available, initializes the {@link DefaultLoginPageViewFilter} shared object.
+     * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object.
      *
      * @param http the {@link HttpSecurityBuilder} to use
      */
     private void initDefaultLoginFilter(H http) {
-        DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
+        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
         if(loginPageGeneratingFilter != null && !isCustomLoginPage()) {
             loginPageGeneratingFilter.setFormLoginEnabled(true);
             loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter());

+ 2 - 2
config/src/main/java/org/springframework/security/config/annotation/web/configurers/LogoutConfigurer.java

@@ -29,7 +29,7 @@ import org.springframework.security.web.authentication.logout.LogoutHandler;
 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
 import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
 import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 
@@ -228,7 +228,7 @@ public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends Ab
             PermitAllSupport.permitAll(http, this.getLogoutRequestMatcher(http));
         }
 
-        DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
+        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
         if(loginPageGeneratingFilter != null && !isCustomLogoutSuccess()) {
             loginPageGeneratingFilter.setLogoutSuccessUrl(getLogoutSuccessUrl());
         }

+ 4 - 4
config/src/main/java/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurer.java

@@ -32,7 +32,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke
 import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
 import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
 import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 
 /**
  * Configures Remember Me authentication. This typically involves the user
@@ -67,7 +67,7 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFi
  * <ul>
  * <li>{@link AuthenticationManager}</li>
  * <li>{@link UserDetailsService} if no {@link #userDetailsService(UserDetailsService)} was specified.</li>
- * <li> {@link DefaultLoginPageViewFilter} - if present will be populated with information from the configuration</li>
+ * <li> {@link DefaultLoginPageGeneratingFilter} - if present will be populated with information from the configuration</li>
  * </ul>
  *
  * @author Rob Winch
@@ -229,12 +229,12 @@ public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>> extend
     }
 
     /**
-     * If available, initializes the {@link DefaultLoginPageViewFilter} shared object.
+     * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object.
      *
      * @param http the {@link HttpSecurityBuilder} to use
      */
     private void initDefaultLoginFilter(H http) {
-        DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
+        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
         if(loginPageGeneratingFilter != null) {
             loginPageGeneratingFilter.setRememberMeParameter(getRememberMeParameter());
         }

+ 3 - 3
config/src/main/java/org/springframework/security/config/annotation/web/configurers/openid/OpenIDLoginConfigurer.java

@@ -49,7 +49,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
 import org.springframework.security.web.authentication.RememberMeServices;
 import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 
@@ -340,12 +340,12 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
     }
 
     /**
-     * If available, initializes the {@link DefaultLoginPageViewFilter} shared object.
+     * If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared object.
      *
      * @param http the {@link HttpSecurityBuilder} to use
      */
     private void initDefaultLoginFilter(H http) {
-        DefaultLoginPageViewFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageViewFilter.class);
+        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
         if(loginPageGeneratingFilter != null && !isCustomLoginPage()) {
             loginPageGeneratingFilter.setOpenIdEnabled(true);
             loginPageGeneratingFilter.setOpenIDauthenticationUrl(getLoginProcessingUrl());

+ 4 - 4
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/DefaultLoginPageConfigurerTests.groovy

@@ -33,7 +33,7 @@ import org.springframework.security.web.access.ExceptionTranslationFilter;
 import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
 import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler
-import org.springframework.security.web.authentication.ui.DefaultLoginPageViewFilter;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
 
 /**
  * Tests to verify that {@link DefaultLoginPageConfigurer} works
@@ -48,7 +48,7 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
         when:
             springSecurityFilterChain.doFilter(request,response,chain)
         then:
-            findFilter(DefaultLoginPageViewFilter)
+            findFilter(DefaultLoginPageGeneratingFilter)
             response.getRedirectedUrl() == "http://localhost/login"
         when: "request the login page"
             super.setup()
@@ -293,7 +293,7 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
         when:
             loadConfig(DefaultLoginWithCustomAuthenticationEntryPointConfig)
         then:
-            !findFilter(DefaultLoginPageViewFilter)
+            !findFilter(DefaultLoginPageGeneratingFilter)
     }
 
     @Configuration
@@ -328,7 +328,7 @@ public class DefaultLoginPageConfigurerTests extends BaseSpringSpec {
                 .build()
 
         then: "DefaultLoginPageGeneratingFilter is registered with LifecycleManager"
-            1 * objectPostProcessor.postProcess(_ as DefaultLoginPageViewFilter) >> {DefaultLoginPageViewFilter o -> o}
+            1 * objectPostProcessor.postProcess(_ as DefaultLoginPageGeneratingFilter) >> {DefaultLoginPageGeneratingFilter o -> o}
             1 * objectPostProcessor.postProcess(_ as UsernamePasswordAuthenticationFilter) >> {UsernamePasswordAuthenticationFilter o -> o}
             1 * objectPostProcessor.postProcess(_ as LoginUrlAuthenticationEntryPoint) >> {LoginUrlAuthenticationEntryPoint o -> o}
             1 * objectPostProcessor.postProcess(_ as ExceptionTranslationFilter) >> {ExceptionTranslationFilter o -> o}

+ 1 - 1
config/src/test/groovy/org/springframework/security/config/http/HttpOpenIDConfigTests.groovy

@@ -99,7 +99,7 @@ class OpenIDConfigTests extends AbstractHttpConfigTests {
         openIDFilter.setReturnToUrlParameters(returnToUrlParameters)
         assert loginFilter.openIDrememberMeParameter != null
 
-        MockHttpServletRequest request = new MockHttpServletRequest();
+        MockHttpServletRequest request = new MockHttpServletRequest(method:'GET');
         MockHttpServletResponse response = new MockHttpServletResponse();
 
         when: "Initial request is made"

+ 6 - 6
samples/messages-jc/pom.xml

@@ -132,18 +132,18 @@
       <artifactId>spring-core</artifactId>
       <version>3.2.4.RELEASE</version>
       <scope>compile</scope>
-      <exclusions>
-        <exclusion>
-          <artifactId>commons-logging</artifactId>
-          <groupId>commons-logging</groupId>
-        </exclusion>
-      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-core</artifactId>
       <version>3.2.4.RELEASE</version>
       <scope>compile</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>commons-logging</artifactId>
+          <groupId>commons-logging</groupId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.springframework</groupId>

+ 104 - 8
web/src/main/java/org/springframework/security/web/authentication/ui/DefaultLoginPageGeneratingFilter.java

@@ -15,6 +15,7 @@ import org.springframework.security.web.WebAttributes;
 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
+import org.springframework.security.web.csrf.CsrfToken;
 import org.springframework.web.filter.GenericFilterBean;
 
 /**
@@ -29,8 +30,11 @@ import org.springframework.web.filter.GenericFilterBean;
 public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
     public static final String DEFAULT_LOGIN_PAGE_URL = "/spring_security_login";
     public static final String ERROR_PARAMETER_NAME = "login_error";
-    boolean formLoginEnabled;
-    boolean openIdEnabled;
+    private String loginPageUrl;
+    private String logoutSuccessUrl;
+    private String failureUrl;
+    private boolean formLoginEnabled;
+    private boolean openIdEnabled;
     private String authenticationUrl;
     private String usernameParameter;
     private String passwordParameter;
@@ -39,6 +43,8 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
     private String openIDusernameParameter;
     private String openIDrememberMeParameter;
 
+    public DefaultLoginPageGeneratingFilter() {}
+
     public DefaultLoginPageGeneratingFilter(AbstractAuthenticationProcessingFilter filter) {
         if (filter instanceof UsernamePasswordAuthenticationFilter) {
             init((UsernamePasswordAuthenticationFilter)filter, null);
@@ -52,6 +58,9 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
     }
 
     private void init(UsernamePasswordAuthenticationFilter authFilter, AbstractAuthenticationProcessingFilter openIDFilter) {
+        this.loginPageUrl = DEFAULT_LOGIN_PAGE_URL;
+        this.logoutSuccessUrl = DEFAULT_LOGIN_PAGE_URL + "?logout";
+        this.failureUrl = DEFAULT_LOGIN_PAGE_URL + "?" + ERROR_PARAMETER_NAME;
         if (authFilter != null) {
             formLoginEnabled = true;
             authenticationUrl = authFilter.getFilterProcessesUrl();
@@ -74,13 +83,68 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
         }
     }
 
+    public boolean isEnabled() {
+        return formLoginEnabled || openIdEnabled;
+    }
+
+    public void setLogoutSuccessUrl(String logoutSuccessUrl) {
+        this.logoutSuccessUrl = logoutSuccessUrl;
+    }
+
+    public String getLoginPageUrl() {
+        return loginPageUrl;
+    }
+
+    public void setLoginPageUrl(String loginPageUrl) {
+        this.loginPageUrl = loginPageUrl;
+    }
+
+    public void setFailureUrl(String failureUrl) {
+        this.failureUrl = failureUrl;
+    }
+
+    public void setFormLoginEnabled(boolean formLoginEnabled) {
+        this.formLoginEnabled = formLoginEnabled;
+    }
+
+    public void setOpenIdEnabled(boolean openIdEnabled) {
+        this.openIdEnabled = openIdEnabled;
+    }
+
+    public void setAuthenticationUrl(String authenticationUrl) {
+        this.authenticationUrl = authenticationUrl;
+    }
+
+    public void setUsernameParameter(String usernameParameter) {
+        this.usernameParameter = usernameParameter;
+    }
+
+    public void setPasswordParameter(String passwordParameter) {
+        this.passwordParameter = passwordParameter;
+    }
+
+    public void setRememberMeParameter(String rememberMeParameter) {
+        this.rememberMeParameter = rememberMeParameter;
+        this.openIDrememberMeParameter = rememberMeParameter;
+    }
+
+    public void setOpenIDauthenticationUrl(String openIDauthenticationUrl) {
+        this.openIDauthenticationUrl = openIDauthenticationUrl;
+    }
+
+    public void setOpenIDusernameParameter(String openIDusernameParameter) {
+        this.openIDusernameParameter = openIDusernameParameter;
+    }
+
     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
             throws IOException, ServletException {
         HttpServletRequest request = (HttpServletRequest) req;
         HttpServletResponse response = (HttpServletResponse) res;
 
-        if (isLoginUrlRequest(request)) {
-            String loginPageHtml = generateLoginPageHtml(request);
+        boolean loginError = isErrorPage(request);
+        boolean logoutSuccess = isLogoutSuccess(request);
+        if (isLoginUrlRequest(request) || loginError || logoutSuccess) {
+            String loginPageHtml = generateLoginPageHtml(request, loginError, logoutSuccess);
             response.setContentType("text/html;charset=UTF-8");
             response.setContentLength(loginPageHtml.length());
             response.getWriter().write(loginPageHtml);
@@ -91,8 +155,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
         chain.doFilter(request, response);
     }
 
-    private String generateLoginPageHtml(HttpServletRequest request) {
-        boolean loginError = request.getParameter(ERROR_PARAMETER_NAME) != null;
+    private String generateLoginPageHtml(HttpServletRequest request, boolean loginError, boolean logoutSuccess) {
         String errorMsg = "none";
 
         if (loginError) {
@@ -118,6 +181,10 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
             sb.append("</font></p>");
         }
 
+        if (logoutSuccess) {
+            sb.append("<p><font color='green'>You have been logged out</font></p>");
+        }
+
         if (formLoginEnabled) {
             sb.append("<h3>Login with Username and Password</h3>");
             sb.append("<form name='f' action='").append(request.getContextPath()).append(authenticationUrl).append("' method='POST'>\n");
@@ -131,6 +198,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
             }
 
             sb.append("    <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
+            renderHiddenInputs(sb, request);
             sb.append("  </table>\n");
             sb.append("</form>");
         }
@@ -148,6 +216,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
 
             sb.append("    <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
             sb.append("  </table>\n");
+            renderHiddenInputs(sb, request);
             sb.append("</form>");
         }
 
@@ -156,7 +225,30 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
         return sb.toString();
     }
 
+    private void renderHiddenInputs(StringBuilder sb, HttpServletRequest request) {
+        CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
+
+        if(token != null) {
+            sb.append("    <input name=\""+ token.getParameterName() +"\" type=\"hidden\" value=\""+ token.getToken() +"\" />\n");
+        }
+    }
+
+    private boolean isLogoutSuccess(HttpServletRequest request) {
+        return logoutSuccessUrl != null && matches(request, logoutSuccessUrl);
+    }
+
     private boolean isLoginUrlRequest(HttpServletRequest request) {
+        return matches(request, loginPageUrl);
+    }
+
+    private boolean isErrorPage(HttpServletRequest request) {
+        return matches(request, failureUrl);
+    }
+
+    private boolean matches(HttpServletRequest request, String url) {
+        if(!"GET".equals(request.getMethod()) || url == null) {
+            return false;
+        }
         String uri = request.getRequestURI();
         int pathParamIndex = uri.indexOf(';');
 
@@ -165,10 +257,14 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
             uri = uri.substring(0, pathParamIndex);
         }
 
+        if(request.getQueryString() != null) {
+            uri += "?" + request.getQueryString();
+        }
+
         if ("".equals(request.getContextPath())) {
-            return uri.endsWith(DEFAULT_LOGIN_PAGE_URL);
+            return uri.endsWith(url);
         }
 
-        return uri.endsWith(request.getContextPath() + DEFAULT_LOGIN_PAGE_URL);
+        return uri.endsWith(request.getContextPath() + url);
     }
 }

+ 0 - 237
web/src/main/java/org/springframework/security/web/authentication/ui/DefaultLoginPageViewFilter.java

@@ -1,237 +0,0 @@
-/*
- * Copyright 2002-2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.web.authentication.ui;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.web.WebAttributes;
-import org.springframework.security.web.csrf.CsrfToken;
-import org.springframework.web.filter.GenericFilterBean;
-
-/**
- * This class generates a default login page if one was not specified.
- *
- * @author Rob Winch
- * @since 3.2
- */
-public class DefaultLoginPageViewFilter extends GenericFilterBean {
-    private String loginPageUrl;
-    private String logoutSuccessUrl;
-    private String failureUrl;
-    private boolean formLoginEnabled;
-    private boolean openIdEnabled;
-    private String authenticationUrl;
-    private String usernameParameter;
-    private String passwordParameter;
-    private String rememberMeParameter;
-    private String openIDauthenticationUrl;
-    private String openIDusernameParameter;
-    private String openIDrememberMeParameter;
-
-    public boolean isEnabled() {
-        return formLoginEnabled || openIdEnabled;
-    }
-
-    public void setLogoutSuccessUrl(String logoutSuccessUrl) {
-        this.logoutSuccessUrl = logoutSuccessUrl;
-    }
-
-    public String getLoginPageUrl() {
-        return loginPageUrl;
-    }
-
-    public void setLoginPageUrl(String loginPageUrl) {
-        this.loginPageUrl = loginPageUrl;
-    }
-
-    public void setFailureUrl(String failureUrl) {
-        this.failureUrl = failureUrl;
-    }
-
-    public void setFormLoginEnabled(boolean formLoginEnabled) {
-        this.formLoginEnabled = formLoginEnabled;
-    }
-
-    public void setOpenIdEnabled(boolean openIdEnabled) {
-        this.openIdEnabled = openIdEnabled;
-    }
-
-    public void setAuthenticationUrl(String authenticationUrl) {
-        this.authenticationUrl = authenticationUrl;
-    }
-
-    public void setUsernameParameter(String usernameParameter) {
-        this.usernameParameter = usernameParameter;
-    }
-
-    public void setPasswordParameter(String passwordParameter) {
-        this.passwordParameter = passwordParameter;
-    }
-
-    public void setRememberMeParameter(String rememberMeParameter) {
-        this.rememberMeParameter = rememberMeParameter;
-        this.openIDrememberMeParameter = rememberMeParameter;
-    }
-
-    public void setOpenIDauthenticationUrl(String openIDauthenticationUrl) {
-        this.openIDauthenticationUrl = openIDauthenticationUrl;
-    }
-
-    public void setOpenIDusernameParameter(String openIDusernameParameter) {
-        this.openIDusernameParameter = openIDusernameParameter;
-    }
-
-    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
-            throws IOException, ServletException {
-        HttpServletRequest request = (HttpServletRequest) req;
-        HttpServletResponse response = (HttpServletResponse) res;
-
-        boolean loginError = isErrorPage(request);
-        boolean logoutSuccess = isLogoutSuccess(request);
-        if (isLoginUrlRequest(request) || loginError || logoutSuccess) {
-            String loginPageHtml = generateLoginPageHtml(request, loginError, logoutSuccess);
-            response.setContentType("text/html;charset=UTF-8");
-            response.setContentLength(loginPageHtml.length());
-            response.getWriter().write(loginPageHtml);
-
-            return;
-        }
-
-        chain.doFilter(request, response);
-    }
-
-    private String generateLoginPageHtml(HttpServletRequest request, boolean loginError, boolean logoutSuccess) {
-        String errorMsg = "none";
-
-        if (loginError) {
-            HttpSession session = request.getSession(false);
-
-            if(session != null) {
-                AuthenticationException ex = (AuthenticationException) session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
-                errorMsg = ex != null ? ex.getMessage() : "none";
-            }
-        }
-
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("<html><head><title>Login Page</title></head>");
-
-        if (formLoginEnabled) {
-            sb.append("<body onload='document.f.").append(usernameParameter).append(".focus();'>\n");
-        }
-
-        if (loginError) {
-            sb.append("<p><font color='red'>Your login attempt was not successful, try again.<br/><br/>Reason: ");
-            sb.append(errorMsg);
-            sb.append("</font></p>");
-        }
-
-        if (logoutSuccess) {
-            sb.append("<p><font color='green'>You have been logged out</font></p>");
-        }
-
-        if (formLoginEnabled) {
-            sb.append("<h3>Login with Username and Password</h3>");
-            sb.append("<form name='f' action='").append(request.getContextPath()).append(authenticationUrl).append("' method='POST'>\n");
-            sb.append(" <table>\n");
-            sb.append("    <tr><td>User:</td><td><input type='text' name='");
-            sb.append(usernameParameter).append("' value='").append("'></td></tr>\n");
-            sb.append("    <tr><td>Password:</td><td><input type='password' name='").append(passwordParameter).append("'/></td></tr>\n");
-
-            if (rememberMeParameter != null) {
-                sb.append("    <tr><td><input type='checkbox' name='").append(rememberMeParameter).append("'/></td><td>Remember me on this computer.</td></tr>\n");
-            }
-
-            sb.append("    <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
-            renderHiddenInputs(sb, request);
-            sb.append("  </table>\n");
-            sb.append("</form>");
-        }
-
-        if(openIdEnabled) {
-            sb.append("<h3>Login with OpenID Identity</h3>");
-            sb.append("<form name='oidf' action='").append(request.getContextPath()).append(openIDauthenticationUrl).append("' method='POST'>\n");
-            sb.append(" <table>\n");
-            sb.append("    <tr><td>Identity:</td><td><input type='text' size='30' name='");
-            sb.append(openIDusernameParameter).append("'/></td></tr>\n");
-
-            if (openIDrememberMeParameter != null) {
-                sb.append("    <tr><td><input type='checkbox' name='").append(openIDrememberMeParameter).append("'></td><td>Remember me on this computer.</td></tr>\n");
-            }
-
-            sb.append("    <tr><td colspan='2'><input name=\"submit\" type=\"submit\" value=\"Login\"/></td></tr>\n");
-            sb.append("  </table>\n");
-            renderHiddenInputs(sb, request);
-            sb.append("</form>");
-        }
-
-        sb.append("</body></html>");
-
-        return sb.toString();
-    }
-
-    private void renderHiddenInputs(StringBuilder sb, HttpServletRequest request) {
-        CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
-
-        if(token != null) {
-            sb.append("    <input name=\""+ token.getParameterName() +"\" type=\"hidden\" value=\""+ token.getToken() +"\" />\n");
-        }
-    }
-
-    private boolean isLogoutSuccess(HttpServletRequest request) {
-        return logoutSuccessUrl != null && matches(request, logoutSuccessUrl);
-    }
-
-    private boolean isLoginUrlRequest(HttpServletRequest request) {
-        return matches(request, loginPageUrl);
-    }
-
-    private boolean isErrorPage(HttpServletRequest request) {
-        return matches(request, failureUrl);
-    }
-
-    private boolean matches(HttpServletRequest request, String url) {
-        if(!"GET".equals(request.getMethod()) || url == null) {
-            return false;
-        }
-        String uri = request.getRequestURI();
-        int pathParamIndex = uri.indexOf(';');
-
-        if (pathParamIndex > 0) {
-            // strip everything after the first semi-colon
-            uri = uri.substring(0, pathParamIndex);
-        }
-
-        if(request.getQueryString() != null) {
-            uri += "?" + request.getQueryString();
-        }
-
-        if ("".equals(request.getContextPath())) {
-            return uri.endsWith(url);
-        }
-
-        return uri.endsWith(request.getContextPath() + url);
-    }
-}