Java tutorial
/* * This software was designed and created by Jason Carroll. * Copyright (c) 2002, 2003, 2004 Jason Carroll. * The author can be reached at jcarroll@cowsultants.com * ITracker website: http://www.cowsultants.com * ITracker forums: http://www.cowsultants.com/phpBB/index.php * * This program is free software; you can redistribute it and/or modify * it only 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. */ package org.itracker.web.util; import org.itracker.core.AuthenticationConstants; import org.itracker.core.resources.ITrackerResources; import org.itracker.model.*; import org.itracker.model.util.UserUtilities; import org.itracker.services.UserService; import org.itracker.services.authentication.ITrackerUserDetails; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.security.Principal; import java.util.*; public class LoginUtilities { private static final Logger logger = LoggerFactory.getLogger(LoginUtilities.class); private static final int DEFAULT_SESSION_TIMEOUT = 30; public static boolean checkAutoLogin(HttpServletRequest request, boolean allowSaveLogin) { boolean foundLogin = false; if (request != null) { int authType = getRequestAuthType(request); // Check for auto login in request if (authType == AuthenticationConstants.AUTH_TYPE_REQUEST) { String redirectURL = request.getRequestURI().substring(request.getContextPath().length()) + (request.getQueryString() != null ? "?" + request.getQueryString() : ""); request.setAttribute(Constants.AUTH_TYPE_KEY, AuthenticationConstants.AUTH_TYPE_REQUEST); request.setAttribute(Constants.AUTH_REDIRECT_KEY, redirectURL); request.setAttribute("processLogin", "true"); foundLogin = true; } // Add in check for client certs // Check for auto login with cookies, this will only happen if users // are allowed to save // their logins to cookies if (allowSaveLogin && !foundLogin) { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (Constants.COOKIE_NAME.equals(cookie.getName())) { int seperator = cookie.getValue().indexOf('~'); final String login; if (seperator > 0) { login = cookie.getValue().substring(0, seperator); if (logger.isDebugEnabled()) { logger.debug("Attempting autologin for user " + login + "."); } String redirectURL = request.getRequestURI() .substring(request.getContextPath().length()) + (request.getQueryString() != null ? "?" + request.getQueryString() : ""); request.setAttribute(Constants.AUTH_LOGIN_KEY, cookie.getValue().substring(0, seperator)); request.setAttribute(Constants.AUTH_TYPE_KEY, AuthenticationConstants.AUTH_TYPE_PASSWORD_ENC); request.setAttribute(Constants.AUTH_VALUE_KEY, cookie.getValue().substring(seperator + 1)); request.setAttribute(Constants.AUTH_REDIRECT_KEY, redirectURL); request.setAttribute("processLogin", "true"); foundLogin = true; } } } } } } return foundLogin; } public static int getRequestAuthType(HttpServletRequest request) { int authType = AuthenticationConstants.AUTH_TYPE_UNKNOWN; try { if (request.getAttribute(Constants.AUTH_TYPE_KEY) != null) { authType = (Integer) request.getAttribute(Constants.AUTH_TYPE_KEY); } if (request.getParameter(Constants.AUTH_TYPE_KEY) != null) { authType = Integer.valueOf(request.getParameter(Constants.AUTH_TYPE_KEY)); } } catch (Exception e) { logger.debug("Error retrieving auth type while checking auto login. " + e.getMessage()); } return authType; } /** * Get a locale from request * <p/> * <p> * TODO the order of retrieving locale from request should be: * <ol> * <li>request-attribute Constants.LOCALE_KEY</li> * <li>request-param 'loc'</li> * <li>session attribute <code>Constants.LOCALE_KEY</code></li> * <li>cookie 'loc'</li> * <li>request.getLocale()/request.getLocales()</li> * <li>ITrackerResources.DEFAULT_LOCALE</li> * </ol> * </p> */ @SuppressWarnings("unchecked") public static Locale getCurrentLocale(HttpServletRequest request) { Locale requestLocale = null; HttpSession session = request.getSession(true); try { requestLocale = (Locale) request.getAttribute(Constants.LOCALE_KEY); if (logger.isDebugEnabled()) { logger.debug("getCurrentLocale: request-attribute was {}", requestLocale); } if (null == requestLocale) { // get locale from request param String loc = request.getParameter("loc"); if (null != loc && loc.trim().length() > 1) { requestLocale = ITrackerResources.getLocale(loc); } logger.debug("getCurrentLocale: request-parameter was {}", loc); } if (null == requestLocale) { // get it from the session requestLocale = (Locale) session.getAttribute(Constants.LOCALE_KEY); // if (logger.isDebugEnabled()) { // logger.debug("getCurrentLocale: session-attribute was " // + requestLocale); // } } if (null == requestLocale) { ResourceBundle bundle = ITrackerResources.getBundle(request.getLocale()); if (logger.isDebugEnabled()) { logger.debug("getCurrentLocale: trying request header locale " + request.getLocale()); } if (bundle.getLocale().getLanguage().equals(request.getLocale().getLanguage())) { requestLocale = request.getLocale(); if (logger.isDebugEnabled()) { logger.debug("getCurrentLocale: request-locale was " + requestLocale); } } } // is there no way to detect supported locales of current // installation? if (null == requestLocale) { Enumeration<Locale> locales = (Enumeration<Locale>) request.getLocales(); ResourceBundle bundle; Locale locale; while (locales.hasMoreElements()) { locale = locales.nextElement(); bundle = ITrackerResources.getBundle(locale); logger.debug("getCurrentLocale: request-locales processing {}, bundle: {}", locale, bundle); if (bundle.getLocale().getLanguage().equals(locale.getLanguage())) { requestLocale = locale; logger.debug("getCurrentLocale: request-locales locale was {}", requestLocale); } } } } finally { if (null == requestLocale) { // fall back to default locale requestLocale = ITrackerResources.getLocale(); logger.debug("getCurrentLocale: fallback default locale was {}", requestLocale); } session.setAttribute(Constants.LOCALE_KEY, requestLocale); request.setAttribute(Constants.LOCALE_KEY, requestLocale); request.setAttribute("currLocale", requestLocale); logger.debug("getCurrentLocale: request and session was setup with {}", requestLocale); } return requestLocale; } /** * get current user from request-attribute currUser, if not set from request-session * * @return current user or null if unauthenticated * @throws NullPointerException if the request was null */ @Deprecated public static User getCurrentUser(HttpServletRequest request) { final String remoteUser = request.getRemoteUser(); if (null == remoteUser) { return null; } User currUser = (User) request.getAttribute("currUser"); if (null != currUser && currUser.getLogin().equals(remoteUser)) { if (logger.isDebugEnabled()) { logger.debug("found user in request: " + remoteUser); } } if (null == currUser) { currUser = (User) request.getSession().getAttribute("currUser"); if (null != currUser && currUser.getLogin().equals(remoteUser)) { if (logger.isDebugEnabled()) { logger.debug("found user in session: " + remoteUser); } } } if (null == currUser) { currUser = ServletContextUtils.getItrackerServices().getUserService().getUserByLogin(remoteUser); if (null != currUser && currUser.getLogin().equals(remoteUser)) { if (logger.isDebugEnabled()) { logger.debug("found user by login: " + remoteUser); } } } return currUser; } /** * Utility for accessing the current logged in user's principal * @return current user principal */ public static ITrackerUserDetails getPrincipal() { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof ITrackerUserDetails) { return (ITrackerUserDetails) principal; } return null; } public static Boolean allowSaveLogin(HttpServletRequest request) { return (boolean) request.getAttribute("allowSaveLogin"); } public static User setupSession(String login, HttpServletRequest request, HttpServletResponse response) { if (null == login) { logger.warn("setupSession: null login", (logger.isDebugEnabled() ? new RuntimeException() : null)); throw new IllegalArgumentException("null login"); } UserService userService = ServletContextUtils.getItrackerServices().getUserService(); User user = userService.getUserByLogin(login); if (user != null) { String encPassword = null; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if (Constants.COOKIE_NAME.equals(cookie.getName())) { int seperator = cookie.getValue().indexOf('~'); if (seperator > 0) { encPassword = cookie.getValue().substring(seperator + 1); } } } } return setupSession(user, encPassword, request, response); } return null; } public static User setupSession(User user, String encPassword, HttpServletRequest request, HttpServletResponse response) { if (user == null) { logger.warn("setupSession: null user", (logger.isDebugEnabled() ? new RuntimeException() : null)); throw new IllegalArgumentException("null user"); } UserService userService = ServletContextUtils.getItrackerServices().getUserService(); if (logger.isDebugEnabled()) { logger.debug("Creating new session"); } HttpSession session = request.getSession(true); if (logger.isDebugEnabled()) { logger.debug("Setting session timeout to " + getConfiguredSessionTimeout() + " minutes"); } session.setMaxInactiveInterval(getConfiguredSessionTimeout() * 60); if (logger.isDebugEnabled()) { logger.debug("Setting session tracker"); } session.setAttribute(Constants.SESSION_TRACKER_KEY, new SessionTracker(user.getLogin(), session.getId())); if (logger.isDebugEnabled()) { logger.debug("Setting user information"); } session.setAttribute(Constants.USER_KEY, user); if (logger.isDebugEnabled()) { logger.debug("Setting preferences for user " + user.getLogin()); } UserPreferences userPrefs = user.getPreferences(); // TODO : this is a hack, remove when possible if (userPrefs == null) { logger.warn("setupSession: got user with no preferences!: " + user + " (prefs: " + user.getPreferences() + ")"); userPrefs = new UserPreferences(); } session.setAttribute(Constants.PREFERENCES_KEY, userPrefs); if (logger.isDebugEnabled()) { logger.debug("Setting user " + user + " locale to " + ITrackerResources.getLocale(userPrefs.getUserLocale())); } session.setAttribute(Constants.LOCALE_KEY, ITrackerResources.getLocale(userPrefs.getUserLocale())); // TODO: cookie could be removed Cookie cookie = new Cookie(Constants.COOKIE_NAME, ""); cookie.setPath(request.getContextPath()); cookie.setValue(""); cookie.setMaxAge(0); response.addCookie(cookie); if (logger.isDebugEnabled()) { logger.debug("Setting permissions for user " + user.getLogin()); } Map<Integer, Set<PermissionType>> usersMapOfProjectIdsAndSetOfPermissionTypes = userService .getUsersMapOfProjectIdsAndSetOfPermissionTypes(user, AuthenticationConstants.REQ_SOURCE_WEB); session.setAttribute(Constants.PERMISSIONS_KEY, usersMapOfProjectIdsAndSetOfPermissionTypes); // Reset some session forms session.setAttribute(Constants.SEARCH_QUERY_KEY, null); SessionManager.clearSessionNeedsReset(user.getLogin()); if (logger.isDebugEnabled()) { logger.debug("User session data updated."); } return user; } public static int getConfiguredSessionTimeout() { return (ServletContextUtils.getItrackerServices().getConfigurationService() .getIntegerProperty("web_session_timeout", DEFAULT_SESSION_TIMEOUT)); } @Deprecated public static boolean hasPermission(int permissionNeeded, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { return hasPermission(PermissionType.valueOf(permissionNeeded), request, response); } public static boolean hasPermission(PermissionType permissionNeeded, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { return hasPermission(new PermissionType[] { permissionNeeded }, request, response); } @Deprecated public static boolean hasPermission(PermissionType[] permissionsNeeded, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { UserDetails user = LoginUtilities.getPrincipal(); HttpSession session = request.getSession(false); Map<Integer, Set<PermissionType>> permissions = (session == null) ? null : RequestHelper.getUserPermissions(session); return UserUtilities.hasPermission(permissions, permissionsNeeded); } catch (RuntimeException re) { logger.debug("hasPermission: failed to check permission", re); return false; } } /** * Returns true if the user has any of required permissions for the project. */ public static boolean hasAnyPermission(Project project, PermissionType[] permissionsNeeded) { if (null == permissionsNeeded || permissionsNeeded.length == 0) { permissionsNeeded = PermissionType.values(); } for (PermissionType permissionType : permissionsNeeded) { if (hasPermission(project, permissionType)) { return true; } } return false; } /** * Returns true if the user has all of required permissions for the project. */ public static boolean hasPermission(Project project, PermissionType[] permissionsNeeded) { for (PermissionType permissionType : permissionsNeeded) { if (!hasPermission(project, permissionType)) { return false; } } return true; } /** * Returns true if the user has all the required permissions. * * @param permissionNeeded the permission to check for */ public static boolean hasPermission(PermissionType permissionNeeded) { return hasPermission(null, permissionNeeded); } /** * Returns true if the user has the required permission for the given project. * * @param project project to which permission is checked for * @param permissionNeeded the permission to check for */ public static boolean hasPermission(Project project, PermissionType permissionNeeded) { UserDetails user = getPrincipal(); if (null == user) { return false; } if (permissionNeeded != PermissionType.USER_ADMIN && hasPermission(PermissionType.USER_ADMIN)) { return true; } else if (null != project && permissionNeeded != PermissionType.PRODUCT_ADMIN && hasPermission(project, PermissionType.PRODUCT_ADMIN)) { return true; } Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); String permissionName = permissionNeeded.name(project); for (GrantedAuthority authority : authorities) { if (authority.getAuthority().equals(permissionName)) { return true; } } return false; } /** * Returns true if the user has permission to view the requested issue. * * @param issue an IssueModel of the issue to check view permission for */ public static boolean canViewIssue(Issue issue) { return canViewIssue(issue, getPrincipal()); } /** * Returns true if the user has permission to view the requested issue. * * @param issue an IssueModel of the issue to check view permission for * @param user the user principal of the user to check permission for */ public static boolean canViewIssue(Issue issue, UserDetails user) { if (hasAnyPermission(issue.getProject(), new PermissionType[] { PermissionType.PRODUCT_ADMIN, PermissionType.ISSUE_VIEW_ALL })) { return true; } // TODO option on project that all users can view own issues boolean canViewUsers = true;// hasPermission(issue.getProject(), PermissionType.ISSUE_VIEW_USERS); // I think owner & creator should always be able to view the issue // otherwise it makes no sense of creating the issue itself. // So put these checks before checking permissions for the whole project. if (canViewUsers && issue.getCreator().getLogin().equals(user.getUsername())) { if (logger.isInfoEnabled()) { logger.info("canViewIssue: issue: " + issue + ", user: " + user.getUsername() + ", permission: is creator"); } return true; } if (canViewUsers && issue.getOwner() != null) { if (issue.getOwner().getLogin().equals(user.getUsername())) { if (logger.isInfoEnabled()) { logger.info("canViewIssue: issue: " + issue + ", user: " + user.getUsername() + ", permission: is owner"); } return true; } } return false; } public static boolean canEditIssue(Issue issue) { return canEditIssue(issue, getPrincipal()); } public static boolean canEditIssue(Issue issue, UserDetails user) { if (issue == null) { return false; } if (hasAnyPermission(issue.getProject(), new PermissionType[] { PermissionType.ISSUE_EDIT_ALL })) { return true; } if (!hasPermission(issue.getProject(), PermissionType.ISSUE_EDIT_USERS)) { if (logger.isDebugEnabled()) { logger.debug("canEditIssue: user " + user.getUsername() + " has not permission to edit issue " + issue.getId() + ":" + PermissionType.ISSUE_EDIT_USERS); } return false; } if (issue.getCreator().getLogin().equals(user.getUsername())) { if (logger.isDebugEnabled()) { logger.debug("canEditIssue: user " + user.getUsername() + " is creator of issue " + issue.getId()); } return true; } if (issue.getOwner() != null) { if (issue.getOwner().getLogin().equals(user.getUsername())) { if (logger.isDebugEnabled()) { logger.debug( "canEditIssue: user " + user.getUsername() + " is owner of issue " + issue.getId()); } return true; } } if (logger.isDebugEnabled()) { logger.debug("canEditIssue: user " + user.getUsername() + " could not match permission, denied"); } return false; } }