Java tutorial
/* * Copyright 2015 dactiv * * Licensed 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 com.github.dactiv.fear.user.service.account; import com.github.dactiv.fear.commons.Apis; import com.github.dactiv.fear.commons.Casts; import com.github.dactiv.fear.commons.entity.Mail; import com.github.dactiv.fear.commons.exception.ServiceException; import com.github.dactiv.fear.commons.service.auth.Subjects; import com.github.dactiv.fear.user.service.TokenExpiredException; import com.github.dactiv.fear.user.service.TokenNotFoundException; import com.github.dactiv.fear.user.service.ValidToken; import com.github.dactiv.universe.captcha.entity.ValidResult; import com.github.dactiv.universe.captcha.support.HttpSessionCaptchaManager; import freemarker.template.Configuration; import freemarker.template.Template; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.crypto.hash.Md5Hash; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; import org.springframework.web.context.request.RequestContextHolder; import javax.servlet.http.HttpSession; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * ? * * @author maurice */ @Service public class AccountService { // ???? private final static String DEFAULT_VALID_MAIL_CACHE_NAME = "validMailCache"; // ???? private final static String DEFAULT_FORGOT_PASSWORD_CACHE_NAME = "forgotPasswordCache"; // ????? private final static String DEFAULT_RESET_PASSWORD_CACHE_NAME = "resetPasswordCache"; // ? private final long DEFAULT_VALID_MAIL_EXPIRED_TIME = 86400000L; // ?? private final long DEFAULT_FORGOT_PASSWORD_EXPIRED_TIME = 1800000L; // ??? private final long DEFAULT_RESET_PASSWORD_EXPIRED_TIME = 600000L; @Autowired private Configuration freemarkerConfiguration; @Autowired private CacheManager cacheManager; @Autowired private HttpSessionCaptchaManager captchaManager; // ??? private String validMailCacheName = DEFAULT_VALID_MAIL_CACHE_NAME; // ???? private String forgotPasswordCacheName = DEFAULT_FORGOT_PASSWORD_CACHE_NAME; // ????? private String resetPasswordCacheName = DEFAULT_RESET_PASSWORD_CACHE_NAME; // ? private long validMailExpiredTime = DEFAULT_VALID_MAIL_EXPIRED_TIME; // ?? private long forgotPasswordExpiredTime = DEFAULT_FORGOT_PASSWORD_EXPIRED_TIME; // ??? private long resetPasswordExpiredTime = DEFAULT_RESET_PASSWORD_EXPIRED_TIME; /** * ??? * * @param validMailCacheName ?? */ public void setValidMailCacheName(String validMailCacheName) { this.validMailCacheName = validMailCacheName; } /** * ???? * * @param forgotPasswordCacheName ???? */ public void setForgotPasswordCacheName(String forgotPasswordCacheName) { this.forgotPasswordCacheName = forgotPasswordCacheName; } /** * ????? * * @param resetPasswordCacheName ????? */ public void setResetPasswordCacheName(String resetPasswordCacheName) { this.resetPasswordCacheName = resetPasswordCacheName; } /** * ? * * @param validMailExpiredTime */ public void setValidMailExpiredTime(long validMailExpiredTime) { this.validMailExpiredTime = validMailExpiredTime; } /** * ?? * * @param forgotPasswordExpiredTime ?? */ public void setForgotPasswordExpiredTime(long forgotPasswordExpiredTime) { this.forgotPasswordExpiredTime = forgotPasswordExpiredTime; } /** * ??? * * @param resetPasswordExpiredTime ??? */ public void setResetPasswordExpiredTime(long resetPasswordExpiredTime) { this.resetPasswordExpiredTime = resetPasswordExpiredTime; } /** * * * @param entity map * @return * @throws Exception */ public Map<String, Object> registration(Map<String, Object> entity) throws Exception { entity.put("state", 1); entity.put("nickname", entity.get("username")); entity.put("isAdmin", 0); Apis.invoke("accountService", "registration", entity); return entity; } /** * ??? * * @param mail ??? * @throws Exception */ public void sendValidMail(String mail) throws Exception { Boolean flag = Apis.invoke("accountService", "isUsernameUnique", mail); if (!flag) { throw new ServiceException("" + mail + ""); } Map<String, Object> principal = Subjects.getPrincipal(); String id = new Md5Hash(mail + principal.get("id") + System.currentTimeMillis()).toHex(); ValidToken entity = new MailValidToken(id, new Date(), mail, principal); Cache cache = cacheManager.getCache(validMailCacheName); cache.put(id, entity); Template template = freemarkerConfiguration.getTemplate("registration.ftl", "UTF-8"); String message = FreeMarkerTemplateUtils.processTemplateIntoString(template, entity); Mail mailEntity = new Mail(mail, "?", message, Boolean.TRUE); Apis.invoke("messageService", "sendMail", mailEntity); } /** * ? * * @param id id * */ public void validMail(String id) { Cache cache = cacheManager.getCache(validMailCacheName); MailValidToken entity = cache.get(id, MailValidToken.class); if (entity == null) { throw new TokenNotFoundException("?ID[" + id + "]?"); } try { long creationTime = entity.getCreationDate().getTime(); long currentTime = System.currentTimeMillis(); if (currentTime - creationTime > validMailExpiredTime) { cache.evict(id); throw new TokenExpiredException("ID[" + entity.getId() + "]"); } Map<String, Object> principal = Subjects.getPrincipal(); if (!principal.get("id").equals(entity.getPrincipal().get("id"))) { throw new ServiceException("???"); } principal.put("isBindingMail", 1); principal.put("email", entity.getMail()); Apis.invoke("accountService", "saveUser", principal, new ArrayList<>()); } finally { cache.evict(id); } } /** * ? * * @param username ?? * @param captcha ?? */ public Map<String, Object> forgotPassword(String username, String captcha) throws Exception { HttpSession session = (HttpSession) RequestContextHolder.currentRequestAttributes().getSessionMutex(); captchaManager.setCurrentSession(session); ValidResult validResult = captchaManager.valid(session.getId(), captcha); if (validResult.getIsValid()) { throw new ServiceException(validResult.getMessage()); } Map<String, Object> user = Apis.invoke("accountService", "getUserByUsernameOrEmail", username); if (MapUtils.isEmpty(user)) { throw new ServiceException("?[" + username + "]"); } sendForgetPasswordMail(user); return user; } /** * ??? * * @param user ? * @throws Exception */ private void sendForgetPasswordMail(Map<String, Object> user) throws Exception { String email = Casts.cast(user.get("email"), String.class); if (StringUtils.isEmpty(email)) { throw new ServiceException("?[" + user.get("username") + "]?"); } String id = new Md5Hash(email + user.get("id") + System.currentTimeMillis()).toHex(); ValidToken entity = new ValidToken(id, new Date(), user); Cache cache = cacheManager.getCache(forgotPasswordCacheName); cache.put(id, entity); Map<String, Object> data = new HashMap<>(); data.put("user", user); data.put("vme", entity); Template template = freemarkerConfiguration.getTemplate("forgot-password.ftl", "UTF-8"); String message = FreeMarkerTemplateUtils.processTemplateIntoString(template, data); Mail mailEntity = new Mail(email, "??", message, Boolean.TRUE); Apis.invoke("messageService", "sendMail", mailEntity); } /** * ?? key * * @param id key * * @return ??? map? */ public ValidToken validForgotPassword(String id) { Cache cache = cacheManager.getCache(forgotPasswordCacheName); ValidToken entity = cache.get(id, ValidToken.class); if (entity == null) { throw new TokenNotFoundException("???"); } try { long creationTime = entity.getCreationDate().getTime(); long currentTime = System.currentTimeMillis(); if (currentTime - creationTime > forgotPasswordExpiredTime) { throw new TokenExpiredException("ID[" + entity.getId() + "]"); } } finally { cache.evict(id); } Map<String, Object> principal = entity.getPrincipal(); id = new Md5Hash(principal.get("id").toString() + System.currentTimeMillis()).toHex(); ValidToken validToken = new ValidToken(id, new Date(), principal); cache = cacheManager.getCache(resetPasswordCacheName); cache.put(id, validToken); return validToken; } /** * ?? * * @param id token id * @param password ? */ public void resetPassword(String id, String password, String confirmPassword) { if (!StringUtils.equals(password, confirmPassword)) { throw new ServiceException("????"); } Cache cache = cacheManager.getCache(resetPasswordCacheName); ValidToken entity = cache.get(id, ValidToken.class); if (entity == null) { throw new TokenNotFoundException("???"); } long creationTime = entity.getCreationDate().getTime(); long currentTime = System.currentTimeMillis(); try { if (currentTime - creationTime > resetPasswordExpiredTime) { throw new TokenExpiredException("ID[" + entity.getId() + "]"); } Integer userId = Casts.cast(entity.getPrincipal().get("id"), Integer.class); Apis.invoke("accountService", "updateUserPassword", userId, password); } finally { cache.evict(id); } } }