001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.web.filter; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.log4j.MDC; 020import org.kuali.rice.core.api.CoreApiServiceLocator; 021import org.kuali.rice.core.api.config.property.ConfigurationService; 022import org.kuali.rice.core.api.exception.RiceRuntimeException; 023import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 024import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator; 025import org.kuali.rice.coreservice.framework.parameter.ParameterService; 026import org.kuali.rice.kew.api.KewApiConstants; 027import org.kuali.rice.kim.api.KimConstants; 028import org.kuali.rice.kim.api.identity.AuthenticationService; 029import org.kuali.rice.kim.api.identity.IdentityService; 030import org.kuali.rice.kim.api.identity.principal.Principal; 031import org.kuali.rice.kim.api.permission.PermissionService; 032import org.kuali.rice.kim.api.services.KimApiServiceLocator; 033import org.kuali.rice.krad.UserSession; 034import org.kuali.rice.krad.exception.AuthenticationException; 035import org.kuali.rice.krad.util.KRADConstants; 036import org.kuali.rice.krad.util.KRADUtils; 037 038import javax.servlet.Filter; 039import javax.servlet.FilterChain; 040import javax.servlet.FilterConfig; 041import javax.servlet.ServletException; 042import javax.servlet.ServletRequest; 043import javax.servlet.ServletResponse; 044import javax.servlet.http.Cookie; 045import javax.servlet.http.HttpServletRequest; 046import javax.servlet.http.HttpServletResponse; 047import javax.xml.namespace.QName; 048import java.io.IOException; 049import java.util.Collections; 050import java.util.UUID; 051 052/** 053 * A filter for processing user logins and creating a {@link org.kuali.rice.krad.UserSession} 054 * 055 * @author Kuali Rice Team (rice.collab@kuali.org) 056 * @see org.kuali.rice.krad.UserSession 057 */ 058public class UserLoginFilter implements Filter { 059 060 private static final String MDC_USER = "user"; 061 062 private IdentityService identityService; 063 private PermissionService permissionService; 064 private ConfigurationService kualiConfigurationService; 065 private ParameterService parameterService; 066 067 private FilterConfig filterConfig; 068 069 @Override 070 public void init(FilterConfig config) throws ServletException { 071 this.filterConfig = config; 072 } 073 074 @Override 075 public void doFilter(ServletRequest request, ServletResponse response, 076 FilterChain chain) throws IOException, ServletException { 077 this.doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain); 078 } 079 080 private void doFilter(HttpServletRequest request, HttpServletResponse response, 081 FilterChain chain) throws IOException, ServletException { 082 try { 083 establishUserSession(request); 084 establishSessionCookie(request, response); 085 establishBackdoorUser(request); 086 087 addToMDC(request); 088 089 chain.doFilter(request, response); 090 } finally { 091 removeFromMDC(); 092 } 093 } 094 095 @Override 096 public void destroy() { 097 filterConfig = null; 098 } 099 100 /** 101 * Checks if a user can be authenticated and if so establishes a UserSession for that user. 102 */ 103 private void establishUserSession(HttpServletRequest request) { 104 if (!isUserSessionEstablished(request)) { 105 String principalName = ((AuthenticationService) GlobalResourceLoader.getResourceLoader().getService( 106 new QName("kimAuthenticationService"))).getPrincipalName(request); 107 if (StringUtils.isBlank(principalName)) { 108 throw new AuthenticationException("Blank User from AuthenticationService - This should never happen."); 109 } 110 111 Principal principal = getIdentityService().getPrincipalByPrincipalName(principalName); 112 if (principal == null) { 113 throw new AuthenticationException("Unknown User: " + principalName); 114 } 115 116 if (!isAuthorizedToLogin(principal.getPrincipalId())) { 117 throw new AuthenticationException( 118 "You cannot log in, because you are not an active Kuali user.\nPlease ask someone to activate your account if you need to use Kuali Systems.\nThe user id provided was: " 119 + principalName + ".\n"); 120 } 121 122 final UserSession userSession = new UserSession(principalName); 123 if (userSession.getPerson() == null) { 124 throw new AuthenticationException("Invalid User: " + principalName); 125 } 126 127 request.getSession().setAttribute(KRADConstants.USER_SESSION_KEY, userSession); 128 } 129 } 130 131 /** 132 * checks if the passed in principalId is authorized to log in. 133 */ 134 private boolean isAuthorizedToLogin(String principalId) { 135 return getPermissionService().isAuthorized(principalId, KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, 136 KimConstants.PermissionNames.LOG_IN, Collections.singletonMap("principalId", principalId)); 137 } 138 139 /** 140 * Creates a session id cookie if one does not exists. Write the cookie out to the response with that session id. 141 * Also, sets the cookie on the established user session. 142 */ 143 private void establishSessionCookie(HttpServletRequest request, HttpServletResponse response) { 144 String kualiSessionId = this.getKualiSessionId(request.getCookies()); 145 if (kualiSessionId == null) { 146 kualiSessionId = UUID.randomUUID().toString(); 147 response.addCookie(new Cookie(KRADConstants.KUALI_SESSION_ID, kualiSessionId)); 148 } 149 KRADUtils.getUserSessionFromRequest(request).setKualiSessionId(kualiSessionId); 150 } 151 152 /** 153 * gets the kuali session id from an array of cookies. If a session id does not exist returns null. 154 */ 155 private String getKualiSessionId(final Cookie[] cookies) { 156 if (cookies != null) { 157 for (Cookie cookie : cookies) { 158 if (KRADConstants.KUALI_SESSION_ID.equals(cookie.getName())) { 159 return cookie.getValue(); 160 } 161 } 162 } 163 return null; 164 } 165 166 /** 167 * establishes the backdoor user on the established user id if backdoor capabilities are valid. 168 */ 169 private void establishBackdoorUser(HttpServletRequest request) { 170 final String backdoor = request.getParameter(KRADConstants.BACKDOOR_PARAMETER); 171 if (StringUtils.isNotBlank(backdoor)) { 172 if (!getKualiConfigurationService().getPropertyValueAsString(KRADConstants.PROD_ENVIRONMENT_CODE_KEY) 173 .equalsIgnoreCase(getKualiConfigurationService().getPropertyValueAsString( 174 KRADConstants.ENVIRONMENT_KEY))) { 175 if (getParameterService().getParameterValueAsBoolean(KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE, 176 KRADConstants.DetailTypes.BACKDOOR_DETAIL_TYPE, KewApiConstants.SHOW_BACK_DOOR_LOGIN_IND)) { 177 try { 178 KRADUtils.getUserSessionFromRequest(request).setBackdoorUser(backdoor); 179 } catch (RiceRuntimeException re) { 180 //Ignore so BackdoorAction can redirect to invalid_backdoor_portal 181 } 182 } 183 } 184 } 185 } 186 187 private void addToMDC(HttpServletRequest request) { 188 MDC.put(MDC_USER, KRADUtils.getUserSessionFromRequest(request).getPrincipalName()); 189 } 190 191 private void removeFromMDC() { 192 MDC.remove(MDC_USER); 193 } 194 195 /** 196 * Checks if the user who made the request has a UserSession established 197 * 198 * @param request the HTTPServletRequest object passed in 199 * @return true if the user session has been established, false otherwise 200 */ 201 private boolean isUserSessionEstablished(HttpServletRequest request) { 202 return (request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY) != null); 203 } 204 205 private IdentityService getIdentityService() { 206 if (this.identityService == null) { 207 this.identityService = KimApiServiceLocator.getIdentityService(); 208 } 209 210 return this.identityService; 211 } 212 213 private PermissionService getPermissionService() { 214 if (this.permissionService == null) { 215 this.permissionService = KimApiServiceLocator.getPermissionService(); 216 } 217 218 return this.permissionService; 219 } 220 221 private ConfigurationService getKualiConfigurationService() { 222 if (this.kualiConfigurationService == null) { 223 this.kualiConfigurationService = CoreApiServiceLocator.getKualiConfigurationService(); 224 } 225 226 return this.kualiConfigurationService; 227 } 228 229 private ParameterService getParameterService() { 230 if (this.parameterService == null) { 231 this.parameterService = CoreFrameworkServiceLocator.getParameterService(); 232 } 233 234 return this.parameterService; 235 } 236}