瀏覽代碼

improve login redirect handling

Jason Rivard 8 年之前
父節點
當前提交
21a911b9b2

+ 54 - 0
src/main/java/password/pwm/http/bean/LoginServletBean.java

@@ -0,0 +1,54 @@
+/*
+ * Password Management Servlets (PWM)
+ * http://www.pwm-project.org
+ *
+ * Copyright (c) 2006-2009 Novell, Inc.
+ * Copyright (c) 2009-2016 The PWM Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package password.pwm.http.bean;
+
+import com.google.gson.annotations.SerializedName;
+import password.pwm.config.option.SessionBeanMode;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class LoginServletBean extends PwmSessionBean {
+    @SerializedName("n")
+    private String nextUrl;
+
+    public String getNextUrl() {
+        return nextUrl;
+    }
+
+    public void setNextUrl(final String nextUrl) {
+        this.nextUrl = nextUrl;
+    }
+
+    public Type getType() {
+        return Type.PUBLIC;
+    }
+
+    @Override
+    public Set<SessionBeanMode> supportedModes() {
+        return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(SessionBeanMode.LOCAL, SessionBeanMode.CRYPTCOOKIE)));
+    }
+
+}

+ 36 - 20
src/main/java/password/pwm/http/servlet/LoginServlet.java

@@ -27,19 +27,19 @@ import password.pwm.PwmConstants;
 import password.pwm.bean.UserIdentity;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
-import password.pwm.error.PwmException;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmURL;
+import password.pwm.http.bean.LoginServletBean;
 import password.pwm.ldap.auth.AuthenticationType;
 import password.pwm.ldap.auth.PwmAuthenticationSource;
 import password.pwm.ldap.auth.SessionAuthenticator;
 import password.pwm.util.CaptchaUtility;
 import password.pwm.util.Helper;
 import password.pwm.util.PasswordData;
-import password.pwm.util.Validator;
+import password.pwm.util.StringUtil;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.ws.server.RestResultBean;
 
@@ -74,6 +74,7 @@ public class LoginServlet extends AbstractPwmServlet {
     public enum LoginServletAction implements ProcessAction {
         login(HttpMethod.POST),
         restLogin(HttpMethod.POST),
+        receiveUrl(HttpMethod.GET),
 
         ;
 
@@ -112,8 +113,6 @@ public class LoginServlet extends AbstractPwmServlet {
         final LoginServletAction action = readProcessAction(pwmRequest);
 
         if (action != null) {
-            Validator.validatePwmFormID(pwmRequest);
-
             switch (action) {
                 case login:
                     processLogin(pwmRequest, passwordOnly);
@@ -123,6 +122,10 @@ public class LoginServlet extends AbstractPwmServlet {
                     processRestLogin(pwmRequest, passwordOnly);
                     break;
 
+                case receiveUrl:
+                    processReceiveUrl(pwmRequest);
+                    break;
+
                 default:
                     Helper.unhandledSwitchStatement(action);
             }
@@ -146,10 +149,7 @@ public class LoginServlet extends AbstractPwmServlet {
         }
 
         // login has succeeded
-        pwmRequest.sendRedirect(determinePostLoginUrl(
-                pwmRequest,
-                pwmRequest.readParameterAsString(PwmConstants.PARAM_POST_LOGIN_URL)
-        ));
+        pwmRequest.sendRedirect(determinePostLoginUrl(pwmRequest));
     }
 
     private void processRestLogin(final PwmRequest pwmRequest, final boolean passwordOnly)
@@ -175,7 +175,7 @@ public class LoginServlet extends AbstractPwmServlet {
         pwmRequest.readParametersAsMap();
 
         // login has succeeded
-        final String nextLoginUrl = determinePostLoginUrl(pwmRequest, valueMap.get(PwmConstants.PARAM_POST_LOGIN_URL));
+        final String nextLoginUrl = determinePostLoginUrl(pwmRequest);
         final RestResultBean restResultBean = new RestResultBean();
         final HashMap<String,String> resultMap = new HashMap<>(Collections.singletonMap("nextURL", nextLoginUrl));
         restResultBean.setData(resultMap);
@@ -183,6 +183,22 @@ public class LoginServlet extends AbstractPwmServlet {
         pwmRequest.outputJsonResult(restResultBean);
     }
 
+    private void processReceiveUrl(final PwmRequest pwmRequest)
+            throws PwmUnrecoverableException, IOException
+    {
+        final String encryptedNextUrl = pwmRequest.readParameterAsString(PwmConstants.PARAM_POST_LOGIN_URL);
+        if (!StringUtil.isEmpty(encryptedNextUrl)) {
+            final String nextUrl = pwmRequest.getPwmApplication().getSecureService().decryptStringValue(encryptedNextUrl);
+            if (!StringUtil.isEmpty(nextUrl)) {
+                final LoginServletBean loginServletBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, LoginServletBean.class);
+                LOGGER.trace(pwmRequest, "received nextUrl and storing in module bean, value: " + nextUrl);
+                loginServletBean.setNextUrl(nextUrl);
+            }
+        }
+
+        pwmRequest.sendRedirect(PwmServletDefinition.Login);
+    }
+
     private void handleLoginRequest(
             final PwmRequest pwmRequest,
             final Map<String,String> valueMap,
@@ -241,21 +257,16 @@ public class LoginServlet extends AbstractPwmServlet {
         pwmRequest.forwardToJsp(url);
     }
 
-    private static String determinePostLoginUrl(final PwmRequest pwmRequest, final String inputValue)
+    private static String determinePostLoginUrl(final PwmRequest pwmRequest)
             throws PwmUnrecoverableException
     {
-        String decryptedValue = null;
-        try {
-            if (inputValue != null && !inputValue.isEmpty()) {
-                decryptedValue = pwmRequest.getPwmApplication().getSecureService().decryptStringValue(inputValue);
-            }
-        } catch (PwmException e) {
-            LOGGER.warn(pwmRequest, "unable to decrypt post login redirect parameter: " + e.getMessage());
-        }
+        final LoginServletBean loginServletBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, LoginServletBean.class);
+        final String decryptedValue = loginServletBean.getNextUrl();
 
         if (decryptedValue != null && !decryptedValue.isEmpty()) {
             final PwmURL originalPwmURL = new PwmURL(URI.create(decryptedValue),pwmRequest.getContextPath());
             if (!originalPwmURL.isLoginServlet()) {
+                loginServletBean.setNextUrl(null);
                 return decryptedValue;
             }
         }
@@ -270,13 +281,18 @@ public class LoginServlet extends AbstractPwmServlet {
 
         final String encryptedRedirUrl = pwmRequest.getPwmApplication().getSecureService().encryptToString(originalRequestedUrl);
 
+        final Map<String,String> paramMap = new HashMap<>();
+        paramMap.put(PwmConstants.PARAM_POST_LOGIN_URL, encryptedRedirUrl);
+        paramMap.put(PwmConstants.PARAM_ACTION_REQUEST, LoginServletAction.receiveUrl.toString());
+
         final String redirectUrl = PwmURL.appendAndEncodeUrlParameters(
                 pwmRequest.getContextPath() + PwmServletDefinition.Login.servletUrl(),
-                Collections.singletonMap(PwmConstants.PARAM_POST_LOGIN_URL, encryptedRedirUrl)
+                paramMap
         );
 
-        pwmRequest.sendRedirect(redirectUrl);
+        LOGGER.trace(pwmRequest, "redirecting to self to set nextUrl to: " + originalRequestedUrl);
 
+        pwmRequest.sendRedirect(redirectUrl);
     }
 }
 

+ 0 - 3
src/main/webapp/WEB-INF/jsp/login-passwordonly.jsp

@@ -47,9 +47,6 @@
                 <input type="hidden" name="processAction" value="login">
                 <%@ include file="/WEB-INF/jsp/fragment/cancel-button.jsp" %>
                 <input type="hidden" id="pwmFormID" name="pwmFormID" value="<pwm:FormID/>"/>
-                <input type="hidden" id="<%=PwmConstants.PARAM_POST_LOGIN_URL%>" name="<%=PwmConstants.PARAM_POST_LOGIN_URL%>"
-                       value="<%=StringUtil.escapeHtml(JspUtility.getPwmRequest(pageContext).readParameterAsString(PwmConstants.PARAM_POST_LOGIN_URL))%>"/>
-
             </div>
         </form>
         <br/>

+ 0 - 2
src/main/webapp/WEB-INF/jsp/login.jsp

@@ -47,8 +47,6 @@
                 <div class="formFieldWrapper">
                     <input type="<pwm:value name="<%=PwmValue.passwordFieldType%>"/>" name="password" id="password" placeholder="<pwm:display key="Field_Password"/>" required="required" class="inputfield passwordfield"/>
                 </div>
-                <input type="hidden" id="<%=PwmConstants.PARAM_POST_LOGIN_URL%>" name="<%=PwmConstants.PARAM_POST_LOGIN_URL%>"
-                       value="<%=StringUtil.escapeHtml(JspUtility.getPwmRequest(pageContext).readParameterAsString(PwmConstants.PARAM_POST_LOGIN_URL))%>"/>
                 <%@ include file="/WEB-INF/jsp/fragment/captcha-embed.jsp"%>
                 <div class="buttonbar">
                     <button type="submit" class="btn" <pwm:autofocus/> name="button" id="submitBtn">

+ 46 - 39
src/main/webapp/public/reference/environment.jsp

@@ -72,12 +72,38 @@
             not recommended.
         </p>
         <h3>Setting the Application Path</h3>
-        The following configuration methods are evaluated by the application in this order until a value is found:
-        <ol>
-            <li><a href="#webxml">Servlet <code>web.xml</code></a></li>
+        The following configuration methods are available:
+        <ul>
+            <li><a href="#envvar">Environment Variable (Recommended)</a></li>
             <li><a href="#property">Java System Property</a></li>
-            <li><a href="#envvar">Environment Variable</a></li>
-        </ol>
+            <li><a href="#webxml">Servlet <code>web.xml</code></a></li>
+        </ul>
+        <h3><a id="envvar">Environment Variable (Recommended)</a></h3>
+        <p>The application will read the <b><%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH</b> variable to determine the location of the application path.  Relative paths are not permitted.</p>
+        <p>Because you set this value at the OS level, it will make maintaining and updating the application easier because you will not need to change anything other than applying a new <code>war</code> file.</p>
+        <h3>Linux Example</h3>
+        <div class="codeExample">
+            <code>export <%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH='/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data'</code>
+        </div>
+        <p>This environment variable would typically be set as part of an init or other script file that starts your application server.</p>
+        <h4>Windows Example</h4>
+        <div class="codeExample">
+            <code>set "<%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH=c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data"</code>
+        </div>
+        <p>This environment variable is typically set as part of a <code>.bat</code> file that starts your application server, or possibly as a system-wide environment variable via the windows control panel.</p>
+        <br/>
+        <h3><a id="property">Java System Property</a></h3>
+        <p>The application will read the java system property <b><%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath</b> variable to determine the location of
+            the application path.  Relative paths are not permitted.  These example parameters would be added to the java command
+            line that starts the application server (tomcat) and java process.</p>
+        <h4>Linux Example</h4>
+        <div class="codeExample">
+            <code>-D<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath='/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data'</code>
+        </div>
+        <h4>Windows Example</h4>
+        <div class="codeExample">
+            <code>-D<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath="c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data"</code>
+        </div>
         <h3><a id="webxml">Servlet web.xml</a></h3>
         Modify the servlet <code>WEB-INF/web.xml</code> file.  You must modify the application war file to accomplish this method.  This method accommodates multiple
         applications on a single application server.  File paths must be absolute.
@@ -101,44 +127,11 @@
                 &lt;/context-param&gt;<br/>
             </code>
         </div>
-        <h3><a id="property">Java System Property</a></h3>
-        <p>The application will read the java system property <b><%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath</b> variable to determine the location of
-            the application path.  Relative paths are not permitted.  These example parameters would be added to the java command
-            line that starts the application server (tomcat) and java process.</p>
-        <h4>Linux Example</h4>
-        <div class="codeExample">
-            <code>-D<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath='/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data'</code>
-        </div>
-        <h4>Windows Example</h4>
-        <div class="codeExample">
-            <code>-D<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath="c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data"</code>
-        </div>
-        <h3><a id="envvar">Environment Variable</a></h3>
-        <p>The application will read the <b><%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH</b> variable to determine the location of the application path.  Relative paths are not permitted.</p>
-        <h3>Linux Example</h3>
-        <div class="codeExample">
-            <code>export <%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH='/home/user/<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data'</code>
-        </div>
-        <p>This environment variable would typically be set as part of an init or other script file that starts your application server.</p>
-        <h4>Windows Example</h4>
-        <div class="codeExample">
-            <code>set "<%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH=c:\<%=PwmConstants.PWM_APP_NAME.toLowerCase()%>-data"</code>
-        </div>
-        <p>This environment variable is typically set as part of a <code>.bat</code> file that starts your application server, or possibly as a system-wide environment variable via the windows control panel.</p>
-        <br/><br/>
-        <h2><code>ApplicationFlags</code></h2>
-        <p>Application flags can be set to enable or disable behaviors in <%=PwmConstants.PWM_APP_NAME%>.   By default, no flags are set.  Setting flags is optional.  Flags are specified as a comma seperated
-            list of values.  Values are case sensitive.  In most cases, you will not need to set an application flag.
-            <table>
-        <tr><td><h3>Flag</h3></td><td><h3>Behavior</h3></td></tr>
-        <tr><td>ManageHttps</td><td>Enable the setting category <code><%=PwmSettingCategory.HTTPS_SERVER.getLabel(PwmConstants.DEFAULT_LOCALE)%></code></td></tr>
-        <tr><td>NoFileLock</td><td>Disable the file lock in the application path directory.</td></tr>
-    </table>
         <h3>Linux Example</h3>
         <div class="codeExample">
             <code>export <%=PwmConstants.PWM_APP_NAME%>_APPLICATIONFLAGS='ManageHttps,NoFileLock'</code>
         </div>
-        <br/><br/>
+        <br/>
         <h1>Environment Variable Names and Servlet Context</h1>
         <p>
             The environment variables listed above, such as <code><%=PwmConstants.PWM_APP_NAME%>_APPLICATIONPATH</code> and <code><%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.applicationPath</code> assume the default context name of
@@ -161,6 +154,20 @@
                 <td><code>/acme2/</code></td><td><code><%=PwmConstants.PWM_APP_NAME.toLowerCase()%>.acme2.applicationPath</code></td><td><code><%=PwmConstants.PWM_APP_NAME%>_ACME2_APPLICATIONPATH</code></td>
             </tr>
         </table>
+        <p>In case of conflict, the application path parameters are evaluated in the following order.</p>
+        <ol>
+            <li><a href="#webxml">Servlet <code>web.xml</code></a></li>
+            <li><a href="#property">Java System Property</a></li>
+            <li><a href="#envvar">Environment Variable (Recommended)</a></li>
+        </ol>
+        <h2><code>ApplicationFlags</code></h2>
+        <p>Application flags can be set to enable or disable behaviors in <%=PwmConstants.PWM_APP_NAME%>.   By default, no flags are set.  Setting flags is optional.  Flags are specified as a comma seperated
+            list of values.  Values are case sensitive.  In most cases, you will not need to set an application flag.
+        <table>
+            <tr><td><h3>Flag</h3></td><td><h3>Behavior</h3></td></tr>
+            <tr><td>ManageHttps</td><td>Enable the setting category <code><%=PwmSettingCategory.HTTPS_SERVER.getLabel(PwmConstants.DEFAULT_LOCALE)%></code></td></tr>
+            <tr><td>NoFileLock</td><td>Disable the file lock in the application path directory.</td></tr>
+        </table>
     </div>
 </div>
 <%@ include file="/WEB-INF/jsp/fragment/footer.jsp" %>