001package 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 022import org.apache.commons.configuration.Configuration; 023import org.apache.commons.lang.StringUtils; 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.apache.turbine.Turbine; 027import org.apache.turbine.TurbineConstants; 028import org.apache.turbine.annotation.TurbineConfiguration; 029import org.apache.turbine.annotation.TurbineService; 030import org.apache.turbine.om.security.User; 031import org.apache.turbine.pipeline.PipelineData; 032import org.apache.turbine.services.security.SecurityService; 033import org.apache.turbine.util.RunData; 034 035/** 036 * SessionValidator that requires login for use with Template Services 037 * like Velocity or WebMacro. 038 * 039 * <br> 040 * 041 * Templating services requires a different Session Validator 042 * because of the way it handles screens. If you use the WebMacro or 043 * Velocity Service with the DefaultSessionValidator, users will be able to 044 * bypass login by directly addressing the template using 045 * template/index.wm. This is because the Page class looks for the 046 * keyword "template" in the Path information and if it finds it will 047 * reset the screen using it's lookup mechanism and thereby bypass 048 * Login. 049 * 050 * Note that you will need to set the template.login property to the 051 * login template. 052 * 053 * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a> 054 * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a> 055 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 056 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a> 057 * @version $Id: TemplateSecureSessionValidator.java 1695634 2015-08-13 00:35:47Z tv $ 058 */ 059public class TemplateSecureSessionValidator 060 extends SessionValidator 061{ 062 /** Logging */ 063 private static Log log = LogFactory.getLog( 064 TemplateSecureSessionValidator.class); 065 066 @TurbineService 067 private SecurityService security; 068 069 @TurbineConfiguration 070 private Configuration conf; 071 072 /** 073 * doPerform is virtually identical to DefaultSessionValidator 074 * except that it calls template methods instead of bare screen 075 * methods. For example, it uses <code>setScreenTemplate</code> to 076 * load the tr.props TEMPLATE_LOGIN instead of the default's 077 * setScreen to TurbineConstants.SCREEN_LOGIN. 078 * 079 * @see DefaultSessionValidator 080 * @param pipelineData Turbine information. 081 * @throws Exception The anonymous user could not be obtained 082 * from the security service 083 */ 084 @Override 085 public void doPerform(PipelineData pipelineData) 086 throws Exception 087 { 088 RunData data = getRunData(pipelineData); 089 // Pull user from session. 090 data.populate(); 091 092 // The user may have not logged in, so create a "guest/anonymous" user. 093 if (data.getUser() == null) 094 { 095 log.debug("Fixing up empty User Object!"); 096 User anonymousUser = security.getAnonymousUser(); 097 data.setUser(anonymousUser); 098 data.save(); 099 } 100 101 // This is the secure session validator, so user must be logged in. 102 if (!data.getUser().hasLoggedIn()) 103 { 104 log.debug("User is not logged in!"); 105 106 // only set the message if nothing else has already set it 107 // (e.g. the LogoutUser action). 108 if (StringUtils.isEmpty(data.getMessage())) 109 { 110 data.setMessage(conf.getString(TurbineConstants.LOGIN_MESSAGE)); 111 } 112 113 // Set the screen template to the login page. 114 String loginTemplate = 115 conf.getString(TurbineConstants.TEMPLATE_LOGIN); 116 117 log.debug("Sending User to the Login Screen (" 118 + loginTemplate + ")"); 119 data.getTemplateInfo().setScreenTemplate(loginTemplate); 120 121 // We're not doing any actions buddy! (except action.login which 122 // will have been performed already) 123 data.setAction(null); 124 } 125 126 log.debug("Login Check finished!"); 127 128 // Make sure we have some way to return a response. 129 if (!data.hasScreen() && StringUtils.isEmpty( 130 data.getTemplateInfo().getScreenTemplate())) 131 { 132 String template = conf.getString( 133 TurbineConstants.TEMPLATE_HOMEPAGE); 134 135 if (StringUtils.isNotEmpty(template)) 136 { 137 data.getTemplateInfo().setScreenTemplate(template); 138 } 139 else 140 { 141 data.setScreen(conf.getString( 142 TurbineConstants.SCREEN_HOMEPAGE)); 143 } 144 } 145 146 // The session_access_counter can be placed as a hidden field in 147 // forms. This can be used to prevent a user from using the 148 // browsers back button and submitting stale data. 149 // FIXME!! a template needs to be written to use this with templates. 150 151 if (data.getParameters().containsKey("_session_access_counter") 152 && !security.isAnonymousUser(data.getUser())) 153 { 154 // See comments in screens.error.InvalidState. 155 if (data.getParameters().getInt("_session_access_counter") 156 < (((Integer) data.getUser().getTemp( 157 "_session_access_counter")).intValue() - 1)) 158 { 159 if (data.getTemplateInfo().getScreenTemplate() != null) 160 { 161 data.getUser().setTemp("prev_template", 162 data.getTemplateInfo().getScreenTemplate() 163 .replace('/', ',')); 164 data.getTemplateInfo().setScreenTemplate(conf.getString( 165 TurbineConstants.TEMPLATE_INVALID_STATE)); 166 } 167 else 168 { 169 data.getUser().setTemp("prev_screen", 170 data.getScreen().replace('/', ',')); 171 data.setScreen(conf.getString( 172 TurbineConstants.SCREEN_INVALID_STATE)); 173 } 174 data.getUser().setTemp("prev_parameters", data.getParameters()); 175 data.setAction(""); 176 } 177 } 178 179 // We do not want to allow both a screen and template parameter. 180 // The template parameter is dominant. 181 if (data.getTemplateInfo().getScreenTemplate() != null) 182 { 183 data.setScreen(null); 184 } 185 186 // Comply with Turbine 4.0 standards 187 pipelineData.get(Turbine.class).put(User.class, data.getUser()); 188 } 189}