View Javadoc

1   package org.apache.turbine.modules.actions.sessionvalidator;
2   
3   
4   /*
5    * Copyright 2001-2004 The Apache Software Foundation.
6    *
7    * Licensed under the Apache License, Version 2.0 (the "License")
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  
21  import org.apache.commons.configuration.Configuration;
22  
23  import org.apache.commons.lang.StringUtils;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import org.apache.turbine.Turbine;
29  import org.apache.turbine.TurbineConstants;
30  
31  import org.apache.turbine.pipeline.PipelineData;
32  import org.apache.turbine.services.security.TurbineSecurity;
33  
34  import org.apache.turbine.util.RunData;
35  import org.apache.turbine.util.TurbineException;
36  
37  /***
38   * SessionValidator that requires login for use with Template Services
39   * like Velocity or WebMacro.
40   *
41   * <br>
42   *
43   * Templating services requires a different Session Validator
44   * because of the way it handles screens.  If you use the WebMacro or
45   * Velocity Service with the DefaultSessionValidator, users will be able to
46   * bypass login by directly addressing the template using
47   * template/index.wm.  This is because the Page class looks for the
48   * keyword "template" in the Path information and if it finds it will
49   * reset the screen using it's lookup mechanism and thereby bypass
50   * Login.
51   *
52   * Note that you will need to set the template.login property to the
53   * login template.
54   *
55   * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
56   * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
57   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
58   * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
59   * @version $Id: TemplateSecureSessionValidator.java 222043 2004-12-06 17:47:33Z painter $
60   */
61  public class TemplateSecureSessionValidator
62      extends SessionValidator
63  {
64      /*** Logging */
65      private static Log log = LogFactory.getLog(
66              TemplateSecureSessionValidator.class);
67  
68      /***
69       * doPerform is virtually identical to DefaultSessionValidator
70       * except that it calls template methods instead of bare screen
71       * methods. For example, it uses <code>setScreenTemplate</code> to
72       * load the tr.props TEMPLATE_LOGIN instead of the default's
73       * setScreen to TurbineConstants.SCREEN_LOGIN.
74       * @deprecated Use PipelineData version instead.
75       * @see DefaultSessionValidator
76       * @param data Turbine information.
77       * @throws TurbineException The anonymous user could not be obtained
78       *         from the security service
79       */
80      public void doPerform(RunData data)
81              throws TurbineException
82      {
83          Configuration conf = Turbine.getConfiguration();
84  
85          // Pull user from session.
86          data.populate();
87  
88          // The user may have not logged in, so create a "guest/anonymous" user.
89          if (data.getUser() == null)
90          {
91              log.debug("Fixing up empty User Object!");
92              data.setUser(TurbineSecurity.getAnonymousUser());
93              data.save();
94          }
95  
96          // This is the secure sessionvalidator, so user must be logged in.
97          if (!data.getUser().hasLoggedIn())
98          {
99              log.debug("User is not logged in!");
100 
101             // only set the message if nothing else has already set it
102             // (e.g. the LogoutUser action).
103             if (StringUtils.isEmpty(data.getMessage()))
104             {
105                 data.setMessage(conf.getString(TurbineConstants.LOGIN_MESSAGE));
106             }
107 
108             // Set the screen template to the login page.
109             String loginTemplate =
110                 conf.getString(TurbineConstants.TEMPLATE_LOGIN);
111 
112             log.debug("Sending User to the Login Screen (" 
113                     + loginTemplate + ")");
114             data.getTemplateInfo().setScreenTemplate(loginTemplate);
115 
116             // We're not doing any actions buddy! (except action.login which
117             // will have been performed already)
118             data.setAction(null);
119         }
120 
121         log.debug("Login Check finished!");
122 
123         // Make sure we have some way to return a response.
124         if (!data.hasScreen() && StringUtils.isEmpty(
125                 data.getTemplateInfo().getScreenTemplate()))
126         {
127             String template = conf.getString(
128                     TurbineConstants.TEMPLATE_HOMEPAGE);
129 
130             if (StringUtils.isNotEmpty(template))
131             {
132                 data.getTemplateInfo().setScreenTemplate(template);
133             }
134             else
135             {
136                 data.setScreen(conf.getString(
137                         TurbineConstants.SCREEN_HOMEPAGE));
138             }
139         }
140 
141         // The session_access_counter can be placed as a hidden field in
142         // forms.  This can be used to prevent a user from using the
143         // browsers back button and submitting stale data.
144         // FIXME!! a template needs to be written to use this with templates.
145 
146         if (data.getParameters().containsKey("_session_access_counter")
147                 && !TurbineSecurity.isAnonymousUser(data.getUser()))
148         {
149             // See comments in screens.error.InvalidState.
150             if (data.getParameters().getInt("_session_access_counter") 
151                     < (((Integer) data.getUser().getTemp(
152                     "_session_access_counter")).intValue() - 1))
153             {
154                 if (data.getTemplateInfo().getScreenTemplate() != null)
155                 {
156                     data.getUser().setTemp("prev_template",
157                             data.getTemplateInfo().getScreenTemplate()
158                             .replace('/', ','));
159                     data.getTemplateInfo().setScreenTemplate(conf.getString(
160                             TurbineConstants.TEMPLATE_INVALID_STATE));
161                 }
162                 else
163                 {
164                     data.getUser().setTemp("prev_screen",
165                                            data.getScreen().replace('/', ','));
166                     data.setScreen(conf.getString(
167                             TurbineConstants.SCREEN_INVALID_STATE));
168                 }
169                 data.getUser().setTemp("prev_parameters", data.getParameters());
170                 data.setAction("");
171             }
172         }
173 
174         // We do not want to allow both a screen and template parameter.
175         // The template parameter is dominant.
176         if (data.getTemplateInfo().getScreenTemplate() != null)
177         {
178             data.setScreen(null);
179         }
180     }
181     
182     /***
183      * doPerform is virtually identical to DefaultSessionValidator
184      * except that it calls template methods instead of bare screen
185      * methods. For example, it uses <code>setScreenTemplate</code> to
186      * load the tr.props TEMPLATE_LOGIN instead of the default's
187      * setScreen to TurbineConstants.SCREEN_LOGIN.
188      *
189      * @see DefaultSessionValidator
190      * @param pipelineData Turbine information.
191      * @throws TurbineException The anonymous user could not be obtained
192      *         from the security service
193      */
194     public void doPerform(PipelineData pipelineData)
195     throws TurbineException
196     {
197         RunData data = (RunData) getRunData(pipelineData);
198         doPerform(data);
199     }
200 
201     
202 }