    001    package org.apache.turbine.modules.actions.sessionvalidator;
    002
    003    /*
    004     * Licensed to the Apache Software Foundation (ASF) under one
    005     * or more contributor license agreements.  See the NOTICE file
    006     * distributed with this work for additional information
    007     * regarding copyright ownership.  The ASF licenses this file
    008     * to you under the Apache License, Version 2.0 (the
    009     * "License"); you may not use this file except in compliance
    010     * with the License.  You may obtain a copy of the License at
    011     *
    012     *   http://www.apache.org/licenses/LICENSE-2.0
    013     *
    014     * Unless required by applicable law or agreed to in writing,
    015     * software distributed under the License is distributed on an
    016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    017     * KIND, either express or implied.  See the License for the
    018     * specific language governing permissions and limitations
    019     * under the License.
    020     */
    021
    022    import org.apache.commons.configuration.Configuration;
    023
    024    import org.apache.commons.lang.StringUtils;
    025
    026    import org.apache.commons.logging.Log;
    027    import org.apache.commons.logging.LogFactory;
    028
    029    import org.apache.turbine.Turbine;
    030    import org.apache.turbine.TurbineConstants;
    031
    032    import org.apache.turbine.pipeline.PipelineData;
    033    import org.apache.turbine.services.security.TurbineSecurity;
    034
    035    import org.apache.turbine.util.RunData;
    036    import org.apache.turbine.util.TurbineException;
    037
    038    /**
    039     * SessionValidator that requires login for use with Template Services
    040     * like Velocity or WebMacro.
    041     *
    042     * <br>
    043     *
    044     * Templating services requires a different Session Validator
    045     * because of the way it handles screens.  If you use the WebMacro or
    046     * Velocity Service with the DefaultSessionValidator, users will be able to
    047     * bypass login by directly addressing the template using
    048     * template/index.wm.  This is because the Page class looks for the
    049     * keyword "template" in the Path information and if it finds it will
    050     * reset the screen using it's lookup mechanism and thereby bypass
    051     * Login.
    052     *
    053     * Note that you will need to set the template.login property to the
    054     * login template.
    055     *
    056     * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
    057     * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
    058     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    059     * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
    060     * @version $Id: TemplateSecureSessionValidator.java 1066518 2011-02-02 16:30:53Z ludwig $
    061     */
    062    public class TemplateSecureSessionValidator
    063        extends SessionValidator
    064    {
    065        /** Logging */
    066        private static Log log = LogFactory.getLog(
    067                TemplateSecureSessionValidator.class);
    068
    069        /**
    070         * doPerform is virtually identical to DefaultSessionValidator
    071         * except that it calls template methods instead of bare screen
    072         * methods. For example, it uses <code>setScreenTemplate</code> to
    073         * load the tr.props TEMPLATE_LOGIN instead of the default's
    074         * setScreen to TurbineConstants.SCREEN_LOGIN.
    075         * @deprecated Use PipelineData version instead.
    076         * @see DefaultSessionValidator
    077         * @param data Turbine information.
    078         * @throws TurbineException The anonymous user could not be obtained
    079         *         from the security service
    080         */
    081        @Deprecated
    082        @Override
    083        public void doPerform(RunData data)
    084                throws TurbineException
    085        {
    086            Configuration conf = Turbine.getConfiguration();
    087
    088            // Pull user from session.
    089            data.populate();
    090
    091            // The user may have not logged in, so create a "guest/anonymous" user.
    092            if (data.getUser() == null)
    093            {
    094                log.debug("Fixing up empty User Object!");
    095                data.setUser(TurbineSecurity.getAnonymousUser());
    096                data.save();
    097            }
    098
    099            // This is the secure sessionvalidator, so user must be logged in.
    100            if (!data.getUser().hasLoggedIn())
    101            {
    102                log.debug("User is not logged in!");
    103
    104                // only set the message if nothing else has already set it
    105                // (e.g. the LogoutUser action).
    106                if (StringUtils.isEmpty(data.getMessage()))
    107                {
    108                    data.setMessage(conf.getString(TurbineConstants.LOGIN_MESSAGE));
    109                }
    110
    111                // Set the screen template to the login page.
    112                String loginTemplate =
    113                    conf.getString(TurbineConstants.TEMPLATE_LOGIN);
    114
    115                log.debug("Sending User to the Login Screen ("
    116                        + loginTemplate + ")");
    117                data.getTemplateInfo().setScreenTemplate(loginTemplate);
    118
    119                // We're not doing any actions buddy! (except action.login which
    120                // will have been performed already)
    121                data.setAction(null);
    122            }
    123
    124            log.debug("Login Check finished!");
    125
    126            // Make sure we have some way to return a response.
    127            if (!data.hasScreen() && StringUtils.isEmpty(
    128                    data.getTemplateInfo().getScreenTemplate()))
    129            {
    130                String template = conf.getString(
    131                        TurbineConstants.TEMPLATE_HOMEPAGE);
    132
    133                if (StringUtils.isNotEmpty(template))
    134                {
    135                    data.getTemplateInfo().setScreenTemplate(template);
    136                }
    137                else
    138                {
    139                    data.setScreen(conf.getString(
    140                            TurbineConstants.SCREEN_HOMEPAGE));
    141                }
    142            }
    143
    144            // The session_access_counter can be placed as a hidden field in
    145            // forms.  This can be used to prevent a user from using the
    146            // browsers back button and submitting stale data.
    147            // FIXME!! a template needs to be written to use this with templates.
    148
    149            if (data.getParameters().containsKey("_session_access_counter")
    150                    && !TurbineSecurity.isAnonymousUser(data.getUser()))
    151            {
    152                // See comments in screens.error.InvalidState.
    153                if (data.getParameters().getInt("_session_access_counter")
    154                        < (((Integer) data.getUser().getTemp(
    155                        "_session_access_counter")).intValue() - 1))
    156                {
    157                    if (data.getTemplateInfo().getScreenTemplate() != null)
    158                    {
    159                        data.getUser().setTemp("prev_template",
    160                                data.getTemplateInfo().getScreenTemplate()
    161                                .replace('/', ','));
    162                        data.getTemplateInfo().setScreenTemplate(conf.getString(
    163                                TurbineConstants.TEMPLATE_INVALID_STATE));
    164                    }
    165                    else
    166                    {
    167                        data.getUser().setTemp("prev_screen",
    168                                               data.getScreen().replace('/', ','));
    169                        data.setScreen(conf.getString(
    170                                TurbineConstants.SCREEN_INVALID_STATE));
    171                    }
    172                    data.getUser().setTemp("prev_parameters", data.getParameters());
    173                    data.setAction("");
    174                }
    175            }
    176
    177            // We do not want to allow both a screen and template parameter.
    178            // The template parameter is dominant.
    179            if (data.getTemplateInfo().getScreenTemplate() != null)
    180            {
    181                data.setScreen(null);
    182            }
    183        }
    184
    185        /**
    186         * doPerform is virtually identical to DefaultSessionValidator
    187         * except that it calls template methods instead of bare screen
    188         * methods. For example, it uses <code>setScreenTemplate</code> to
    189         * load the tr.props TEMPLATE_LOGIN instead of the default's
    190         * setScreen to TurbineConstants.SCREEN_LOGIN.
    191         *
    192         * @see DefaultSessionValidator
    193         * @param pipelineData Turbine information.
    194         * @throws TurbineException The anonymous user could not be obtained
    195         *         from the security service
    196         */
    197        @Override
    198        public void doPerform(PipelineData pipelineData)
    199        throws TurbineException
    200        {
    201            RunData data = getRunData(pipelineData);
    202            doPerform(data);
    203        }
    204
    205
    206    }