| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| |
| package org.apache.ofbiz.securityext.login; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.net.URLEncoder; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import javax.servlet.http.Cookie; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpSession; |
| |
| import org.apache.commons.lang.RandomStringUtils; |
| import org.apache.ofbiz.base.crypto.HashCrypt; |
| import org.apache.ofbiz.base.util.Debug; |
| import org.apache.ofbiz.base.util.GeneralException; |
| import org.apache.ofbiz.base.util.UtilFormatOut; |
| import org.apache.ofbiz.base.util.UtilHttp; |
| import org.apache.ofbiz.base.util.UtilMisc; |
| import org.apache.ofbiz.base.util.UtilProperties; |
| import org.apache.ofbiz.base.util.UtilValidate; |
| import org.apache.ofbiz.base.util.string.FlexibleStringExpander; |
| import org.apache.ofbiz.common.login.LoginServices; |
| import org.apache.ofbiz.entity.Delegator; |
| import org.apache.ofbiz.entity.GenericDelegator; |
| import org.apache.ofbiz.entity.GenericEntityException; |
| import org.apache.ofbiz.entity.GenericValue; |
| import org.apache.ofbiz.entity.model.ModelField.EncryptMethod; |
| import org.apache.ofbiz.entity.util.EntityCrypto; |
| import org.apache.ofbiz.entity.util.EntityQuery; |
| import org.apache.ofbiz.entity.util.EntityUtilProperties; |
| import org.apache.ofbiz.party.contact.ContactHelper; |
| import org.apache.ofbiz.product.product.ProductEvents; |
| import org.apache.ofbiz.product.store.ProductStoreWorker; |
| import org.apache.ofbiz.service.GenericServiceException; |
| import org.apache.ofbiz.service.LocalDispatcher; |
| import org.apache.ofbiz.service.ModelService; |
| import org.apache.ofbiz.webapp.control.LoginWorker; |
| |
| /** |
| * LoginEvents - Events for UserLogin and Security handling. |
| */ |
| public class LoginEvents { |
| |
| public static final String module = LoginEvents.class.getName(); |
| public static final String resource = "SecurityextUiLabels"; |
| public static final String usernameCookieName = "OFBiz.Username"; |
| private static final String keyValue = UtilProperties.getPropertyValue(LoginWorker.securityProperties, "login.secret_key_string"); |
| /** |
| * Save USERNAME and PASSWORD for use by auth pages even if we start in non-auth pages. |
| * |
| * @param request The HTTP request object for the current JSP or Servlet request. |
| * @param response The HTTP response object for the current JSP or Servlet request. |
| * @return String |
| */ |
| public static String saveEntryParams(HttpServletRequest request, HttpServletResponse response) { |
| GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin"); |
| HttpSession session = request.getSession(); |
| Delegator delegator = (Delegator) request.getAttribute("delegator"); |
| |
| // save entry login parameters if we don't have a valid login object |
| if (userLogin == null) { |
| |
| String username = request.getParameter("USERNAME"); |
| String password = request.getParameter("PASSWORD"); |
| |
| if ((username != null) && ("true".equalsIgnoreCase(EntityUtilProperties.getPropertyValue("security", "username.lowercase", delegator)))) { |
| username = username.toLowerCase(); |
| } |
| if ((password != null) && ("true".equalsIgnoreCase(EntityUtilProperties.getPropertyValue("security", "password.lowercase", delegator)))) { |
| password = password.toLowerCase(); |
| } |
| |
| // save parameters into the session - so they can be used later, if needed |
| if (username != null) session.setAttribute("USERNAME", username); |
| if (password != null) session.setAttribute("PASSWORD", password); |
| |
| } else { |
| // if the login object is valid, remove attributes |
| session.removeAttribute("USERNAME"); |
| session.removeAttribute("PASSWORD"); |
| } |
| |
| return "success"; |
| } |
| |
| /** |
| * The user forgot his/her password. This will call showPasswordHint, emailPassword or simply returns "success" in case |
| * no operation has been specified. |
| * |
| * @param request The HTTPRequest object for the current request |
| * @param response The HTTPResponse object for the current request |
| * @return String specifying the exit status of this event |
| */ |
| public static String forgotPassword(HttpServletRequest request, HttpServletResponse response) { |
| GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator"); |
| String questionEnumId = request.getParameter("securityQuestion"); |
| String securityAnswer = request.getParameter("securityAnswer"); |
| String userLoginId = request.getParameter("USERNAME"); |
| String errMsg = null; |
| |
| try { |
| GenericValue userLoginSecurityQuestion = delegator.findOne("UserLoginSecurityQuestion", UtilMisc.toMap("questionEnumId", questionEnumId, "userLoginId", userLoginId), true); |
| if (userLoginSecurityQuestion != null) { |
| if (UtilValidate.isEmpty(securityAnswer)) { |
| errMsg = UtilProperties.getMessage(resource, "loginservices.security_answer_empty", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| String ulSecurityAnswer = userLoginSecurityQuestion.getString("securityAnswer"); |
| if (UtilValidate.isNotEmpty(ulSecurityAnswer) && !securityAnswer.equalsIgnoreCase(ulSecurityAnswer)) { |
| errMsg = UtilProperties.getMessage(resource, "loginservices.security_answer_not_match", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| } |
| } catch (GenericEntityException e) { |
| errMsg = UtilProperties.getMessage(resource, "loginevents.problem_getting_security_question_record", UtilHttp.getLocale(request)); |
| Debug.logError(e, errMsg, module); |
| } |
| if ((UtilValidate.isNotEmpty(request.getParameter("GET_PASSWORD_HINT"))) || (UtilValidate.isNotEmpty(request.getParameter("GET_PASSWORD_HINT.x")))) { |
| return showPasswordHint(request, response); |
| } else if ((UtilValidate.isNotEmpty(request.getParameter("EMAIL_PASSWORD"))) || (UtilValidate.isNotEmpty(request.getParameter("EMAIL_PASSWORD.x")))) { |
| return emailPassword(request, response); |
| } else { |
| return "success"; |
| } |
| } |
| |
| /** Show the password hint for the userLoginId specified in the request object. |
| *@param request The HTTPRequest object for the current request |
| *@param response The HTTPResponse object for the current request |
| *@return String specifying the exit status of this event |
| */ |
| public static String showPasswordHint(HttpServletRequest request, HttpServletResponse response) { |
| Delegator delegator = (Delegator) request.getAttribute("delegator"); |
| |
| String userLoginId = request.getParameter("USERNAME"); |
| String errMsg = null; |
| |
| if ((userLoginId != null) && ("true".equals(EntityUtilProperties.getPropertyValue("security", "username.lowercase", delegator)))) { |
| userLoginId = userLoginId.toLowerCase(); |
| } |
| |
| if (UtilValidate.isEmpty(userLoginId)) { |
| // the password was incomplete |
| errMsg = UtilProperties.getMessage(resource, "loginevents.username_was_empty_reenter", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| GenericValue supposedUserLogin = null; |
| |
| try { |
| supposedUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne(); |
| } catch (GenericEntityException gee) { |
| Debug.logWarning(gee, "", module); |
| } |
| if (supposedUserLogin == null) { |
| // the Username was not found |
| errMsg = UtilProperties.getMessage(resource, "loginevents.username_not_found_reenter", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| String passwordHint = supposedUserLogin.getString("passwordHint"); |
| |
| if (UtilValidate.isEmpty(passwordHint)) { |
| // the Username was not found |
| errMsg = UtilProperties.getMessage(resource, "loginevents.no_password_hint_specified_try_password_emailed", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| Map<String, String> messageMap = UtilMisc.toMap("passwordHint", passwordHint); |
| errMsg = UtilProperties.getMessage(resource, "loginevents.password_hint_is", messageMap, UtilHttp.getLocale(request)); |
| request.setAttribute("_EVENT_MESSAGE_", errMsg); |
| return "success"; |
| } |
| |
| /** |
| * Email the password for the userLoginId specified in the request object. |
| * |
| * @param request The HTTPRequest object for the current request |
| * @param response The HTTPResponse object for the current request |
| * @return String specifying the exit status of this event |
| */ |
| public static String emailPassword(HttpServletRequest request, HttpServletResponse response) { |
| String defaultScreenLocation = "component://securityext/widget/EmailSecurityScreens.xml#PasswordEmail"; |
| |
| Delegator delegator = (Delegator) request.getAttribute("delegator"); |
| LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher"); |
| String productStoreId = ProductStoreWorker.getProductStoreId(request); |
| |
| String errMsg = null; |
| |
| boolean useEncryption = "true".equals(EntityUtilProperties.getPropertyValue("security", "password.encrypt", delegator)); |
| |
| String userLoginId = request.getParameter("USERNAME"); |
| |
| if ((userLoginId != null) && ("true".equals(EntityUtilProperties.getPropertyValue("security", "username.lowercase", delegator)))) { |
| userLoginId = userLoginId.toLowerCase(); |
| } |
| |
| if (UtilValidate.isEmpty(userLoginId)) { |
| // the password was incomplete |
| errMsg = UtilProperties.getMessage(resource, "loginevents.username_was_empty_reenter", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| GenericValue supposedUserLogin = null; |
| String passwordToSend = null; |
| String autoPassword = null; |
| try { |
| supposedUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne(); |
| if (supposedUserLogin == null) { |
| // the Username was not found |
| errMsg = UtilProperties.getMessage(resource, "loginevents.username_not_found_reenter", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| if (useEncryption) { |
| // password encrypted, can't send, generate new password and email to user |
| passwordToSend = RandomStringUtils.randomAlphanumeric(EntityUtilProperties.getPropertyAsInteger("security", "password.length.min", 5).intValue()); |
| if ("true".equals(EntityUtilProperties.getPropertyValue("security", "password.lowercase", delegator))){ |
| passwordToSend=passwordToSend.toLowerCase(); |
| } |
| autoPassword = RandomStringUtils.randomAlphanumeric(EntityUtilProperties.getPropertyAsInteger("security", "password.length.min", 5).intValue()); |
| EntityCrypto entityCrypto = new EntityCrypto(delegator,null); |
| try { |
| passwordToSend = entityCrypto.encrypt(keyValue, EncryptMethod.TRUE, (Object) autoPassword); |
| } catch (GeneralException e) { |
| Debug.logWarning(e, "Problem in encryption", module); |
| } |
| supposedUserLogin.set("currentPassword", HashCrypt.cryptUTF8(LoginServices.getHashType(), null, autoPassword)); |
| supposedUserLogin.set("passwordHint", "Auto-Generated Password"); |
| if ("true".equals(EntityUtilProperties.getPropertyValue("security", "password.email_password.require_password_change", delegator))){ |
| supposedUserLogin.set("requirePasswordChange", "Y"); |
| } |
| } else { |
| passwordToSend = supposedUserLogin.getString("currentPassword"); |
| } |
| /* Its a Base64 string, it can contain + and this + will be converted to space after decoding the url. |
| For example: passwordToSend "DGb1s2wgUQmwOBK9FK+fvQ==" will be converted to "DGb1s2wgUQmwOBK9FK fvQ==" |
| So to fix it, done Url encoding of passwordToSend. |
| */ |
| passwordToSend = URLEncoder.encode(passwordToSend, "UTF-8"); |
| } catch (GenericEntityException | UnsupportedEncodingException e) { |
| Debug.logWarning(e, "", module); |
| Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.toString()); |
| errMsg = UtilProperties.getMessage(resource, "loginevents.error_accessing_password", messageMap, UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| StringBuilder emails = new StringBuilder(); |
| GenericValue party = null; |
| |
| try { |
| party = supposedUserLogin.getRelatedOne("Party", false); |
| } catch (GenericEntityException e) { |
| Debug.logWarning(e, "", module); |
| party = null; |
| } |
| if (party != null) { |
| Iterator<GenericValue> emailIter = UtilMisc.toIterator(ContactHelper.getContactMechByPurpose(party, "PRIMARY_EMAIL", false)); |
| while (emailIter != null && emailIter.hasNext()) { |
| GenericValue email = emailIter.next(); |
| emails.append(emails.length() > 0 ? "," : "").append(email.getString("infoString")); |
| } |
| } |
| |
| if (UtilValidate.isEmpty(emails.toString())) { |
| // the Username was not found |
| errMsg = UtilProperties.getMessage(resource, "loginevents.no_primary_email_address_set_contact_customer_service", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| // get the ProductStore email settings |
| GenericValue productStoreEmail = null; |
| try { |
| productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "PRDS_PWD_RETRIEVE").queryOne(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, "Problem getting ProductStoreEmailSetting", module); |
| } |
| |
| String bodyScreenLocation = null; |
| if (productStoreEmail != null) { |
| bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation"); |
| } |
| if (UtilValidate.isEmpty(bodyScreenLocation)) { |
| bodyScreenLocation = defaultScreenLocation; |
| } |
| |
| // set the needed variables in new context |
| Map<String, Object> bodyParameters = new HashMap<String, Object>(); |
| bodyParameters.put("useEncryption", Boolean.valueOf(useEncryption)); |
| bodyParameters.put("password", UtilFormatOut.checkNull(passwordToSend)); |
| bodyParameters.put("locale", UtilHttp.getLocale(request)); |
| bodyParameters.put("userLogin", supposedUserLogin); |
| bodyParameters.put("productStoreId", productStoreId); |
| |
| Map<String, Object> serviceContext = new HashMap<String, Object>(); |
| serviceContext.put("bodyScreenUri", bodyScreenLocation); |
| serviceContext.put("bodyParameters", bodyParameters); |
| if (productStoreEmail != null) { |
| serviceContext.put("subject", productStoreEmail.getString("subject")); |
| serviceContext.put("sendFrom", productStoreEmail.get("fromAddress")); |
| serviceContext.put("sendCc", productStoreEmail.get("ccAddress")); |
| serviceContext.put("sendBcc", productStoreEmail.get("bccAddress")); |
| serviceContext.put("contentType", productStoreEmail.get("contentType")); |
| } else { |
| GenericValue emailTemplateSetting = null; |
| try { |
| emailTemplateSetting = EntityQuery.use(delegator).from("EmailTemplateSetting").where("emailTemplateSettingId", "EMAIL_PASSWORD").cache().queryOne(); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, module); |
| } |
| if (emailTemplateSetting != null) { |
| String subject = emailTemplateSetting.getString("subject"); |
| subject = FlexibleStringExpander.expandString(subject, UtilMisc.toMap("userLoginId", userLoginId)); |
| serviceContext.put("subject", subject); |
| serviceContext.put("sendFrom", emailTemplateSetting.get("fromAddress")); |
| } else { |
| serviceContext.put("subject", UtilProperties.getMessage(resource, "loginservices.password_reminder_subject", UtilMisc.toMap("userLoginId", userLoginId), UtilHttp.getLocale(request))); |
| serviceContext.put("sendFrom", EntityUtilProperties.getPropertyValue("general", "defaultFromEmailAddress", delegator)); |
| } |
| } |
| serviceContext.put("sendTo", emails.toString()); |
| serviceContext.put("partyId", party.getString("partyId")); |
| |
| try { |
| Map<String, Object> result = dispatcher.runSync("sendMailHiddenInLogFromScreen", serviceContext); |
| |
| if (ModelService.RESPOND_ERROR.equals(result.get(ModelService.RESPONSE_MESSAGE))) { |
| Map<String, Object> messageMap = UtilMisc.toMap("errorMessage", result.get(ModelService.ERROR_MESSAGE)); |
| errMsg = UtilProperties.getMessage(resource, "loginevents.error_unable_email_password_contact_customer_service_errorwas", messageMap, UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| } catch (GenericServiceException e) { |
| Debug.logWarning(e, "", module); |
| errMsg = UtilProperties.getMessage(resource, "loginevents.error_unable_email_password_contact_customer_service", UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| |
| // don't save password until after it has been sent |
| if (useEncryption) { |
| try { |
| supposedUserLogin.store(); |
| } catch (GenericEntityException e) { |
| Debug.logWarning(e, "", module); |
| Map<String, String> messageMap = UtilMisc.toMap("errorMessage", e.toString()); |
| errMsg = UtilProperties.getMessage(resource, "loginevents.error_saving_new_password_email_not_correct_password", messageMap, UtilHttp.getLocale(request)); |
| request.setAttribute("_ERROR_MESSAGE_", errMsg); |
| return "error"; |
| } |
| } |
| |
| if (useEncryption) { |
| errMsg = UtilProperties.getMessage(resource, "loginevents.new_password_createdandsent_check_email", UtilHttp.getLocale(request)); |
| request.setAttribute("_EVENT_MESSAGE_", errMsg); |
| } else { |
| errMsg = UtilProperties.getMessage(resource, "loginevents.new_password_sent_check_email", UtilHttp.getLocale(request)); |
| request.setAttribute("_EVENT_MESSAGE_", errMsg); |
| } |
| return "success"; |
| } |
| |
| public static String storeCheckLogin(HttpServletRequest request, HttpServletResponse response) { |
| String responseString = LoginWorker.checkLogin(request, response); |
| if ("error".equals(responseString)) { |
| return responseString; |
| } |
| // if we are logged in okay, do the check store customer role |
| return ProductEvents.checkStoreCustomerRole(request, response); |
| } |
| |
| public static String storeLogin(HttpServletRequest request, HttpServletResponse response) { |
| String responseString = LoginWorker.login(request, response); |
| if (!"success".equals(responseString)) { |
| return responseString; |
| } |
| if ("Y".equals(request.getParameter("rememberMe"))) { |
| setUsername(request, response); |
| } |
| // if we logged in okay, do the check store customer role |
| return ProductEvents.checkStoreCustomerRole(request, response); |
| } |
| |
| public static String getUsername(HttpServletRequest request) { |
| String cookieUsername = null; |
| Cookie[] cookies = request.getCookies(); |
| if (Debug.verboseOn()) Debug.logVerbose("Cookies:" + cookies, module); |
| if (cookies != null) { |
| for (Cookie cookie: cookies) { |
| if (cookie.getName().equals(usernameCookieName)) { |
| cookieUsername = cookie.getValue(); |
| break; |
| } |
| } |
| } |
| return cookieUsername; |
| } |
| |
| public static void setUsername(HttpServletRequest request, HttpServletResponse response) { |
| HttpSession session = request.getSession(); |
| Delegator delegator = (Delegator) request.getAttribute("delegator"); |
| String domain = EntityUtilProperties.getPropertyValue("url", "cookie.domain", delegator); |
| // first try to get the username from the cookie |
| synchronized (session) { |
| if (UtilValidate.isEmpty(getUsername(request))) { |
| // create the cookie and send it back |
| Cookie cookie = new Cookie(usernameCookieName, request.getParameter("USERNAME")); |
| cookie.setMaxAge(60 * 60 * 24 * 365); |
| cookie.setPath("/"); |
| cookie.setDomain(domain); |
| response.addCookie(cookie); |
| } |
| } |
| } |
| } |