该模块主要有十个子模块:注册、登陆、用户名/邮箱验证、获取登陆用户信息、登陆状态重置密码、登陆状态下更新用户信息、忘记密码、提交问题答案、重置密码、退出。
1.MD5代码
用户的密码使用MD5加密后存储在数据库当中
package com.mall.util;
import org.springframework.util.StringUtils;
import java.security.MessageDigest;
public class MD5Util {
//内部使用的加密算法
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
//内部使用的加密算法
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
/**
* 返回大写MD5,origin表示原密码
*/
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString.toUpperCase();
}
public static String MD5EncodeUtf8(String origin) {
/**
* 使用下面的句子来进行加盐,直接返回则表示不加盐MD5
*/
origin = origin + PropertiesUtil.getProperty("password.salt", "");
return MD5Encode(origin, "utf-8");
}
private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
}
**********************PropertiesUtil*****************
package com.mall.util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
/**
* Created by geely
*/
public class PropertiesUtil {
private static Logger logger = LoggerFactory.getLogger(PropertiesUtil.class);
private static Properties props;
/**
* PropertiesUtil的实现:要求在Tomcat启动的时候读取到其中的内容
* 所以此处使用静态块来实现,当该类被Java的类加载器加载的时候,就会首先执行static
*/
static {
String fileName = "mall.properties";
props = new Properties();
try {
props.load(new InputStreamReader(PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName),"UTF-8"));
} catch (IOException e) {
logger.error("配置文件读取异常",e);
}
}
public static String getProperty(String key){
String value = props.getProperty(key.trim());
if(StringUtils.isBlank(value)){
return null;
}
return value.trim();
}
public static String getProperty(String key,String defaultValue){
String value = props.getProperty(key.trim());
if(StringUtils.isBlank(value)){
value = defaultValue;
}
return value.trim();
}
}
*************mall.properties***********
password.salt = geelysdafaqj23ou89ZXcj@#$@#$#@KJdjklj;D../dSF.,
2.忘记密码,重置密码时回答问题的答案有效时间
在忘记密码时,一般会有提示问题,通过回答提示问题进行密码的重置,一般在回答问题之后,这个答案在一段时间内时有效的,此处使用google的CacheLoader来存储问题答案的有效时间。
package com.mall.common;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
public class TokenCache {
//日志打印对象
private static Logger logger= LoggerFactory.getLogger(TokenCache.class);
public static final String TOKEN_PREFIX="token_";
/**
* maximumSize:当缓存大大小超过10000的时候会采用最少使用算法,将缓存移除,
* expireAfterAccess:缓存的有效时间是12小时
* build:缓存的实现,此处使用匿名实现
*/
private static LoadingCache localCache= CacheBuilder.newBuilder().initialCapacity(1000).maximumSize(1000)
.expireAfterAccess(12, TimeUnit.HOURS)
.build(new CacheLoader<String, String>() {
//缓存默认的数据加载实现,当调用get取之的时候,如果key没有对应的值,就调用这个方法进行加载
@Override
public String load(String key) throws Exception {
return "null";
}
});
//提供外界的方法
public static void setKey(String key,String value){
localCache.put(key,value);
}
public static String getKey(String key){
String value=null;
try {
value= (String) localCache.get(key);
if("null".equals(value)){
return null;
}
return value;
}catch (Exception e){
logger.info("cache get error",e);
}
return null;
}
}
3.用户管理模块接口(Controller)
package com.mall.controller.portal;
import com.mall.common.Const;
import com.mall.common.ResponseCode;
import com.mall.common.ServerResponse;
import com.mall.pojo.User;
import com.mall.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/user/")
public class UserController {
@Autowired
private IUserService iUserService;
@RequestMapping(value = "login.do",method = RequestMethod.POST)
@ResponseBody
public ServerResponse<User> login(String username, String password, HttpSession session){
ServerResponse<User> serverResponse=iUserService.login(username, password);
if(serverResponse.isSuccess()){
session.setAttribute(Const.CURRENT_USER,serverResponse.getData());
}
return serverResponse;
}
@ResponseBody
@RequestMapping(value = "logout.do")
public ServerResponse logout(HttpSession session){
session.removeAttribute(Const.CURRENT_USER);
return ServerResponse.createBySuccess();
}
@ResponseBody
@RequestMapping(value = "register.do",method = RequestMethod.POST)
public ServerResponse<String> register(User user){
return iUserService.register(user);
}
@ResponseBody
@RequestMapping(value = "check_valid.do",method = RequestMethod.POST)
public ServerResponse<String> checkValid(String str,String type){
return iUserService.checkedValid(str, type);
}
//获取登陆用户的信息
@ResponseBody
@RequestMapping("get_user_information.do")
public ServerResponse<User> getUserInformation(HttpSession session){
User user=(User)session.getAttribute(Const.CURRENT_USER);
if(user==null){
return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getMsg());
}
return ServerResponse.createBySuccess(user);
}
//更新用户信息,然后存放在session当中
@ResponseBody
@RequestMapping("update_user_information.do")
public ServerResponse<User> updateUserInformation(HttpSession session,User updateUser){
User user=(User)session.getAttribute(Const.CURRENT_USER);
if(user==null){
return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getMsg());
}
updateUser.setId(user.getId());
updateUser.setUsername(user.getUsername());
ServerResponse serverResponse=iUserService.updateInformation(updateUser);
if(serverResponse.isSuccess()){
session.setAttribute(Const.CURRENT_USER,serverResponse.getData());
}
return serverResponse;
}
@ResponseBody
@RequestMapping(value = "rest_password.do",method = RequestMethod.POST)
public ServerResponse<User> restPassword(HttpSession session,String oldPassword,String newPassword){
User user=(User)session.getAttribute(Const.CURRENT_USER);
if(user==null){
return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getMsg());
}
return iUserService.restPassword(user.getUsername(),oldPassword,newPassword);
}
//忘记密码:第一步,获取重置密码问题
@ResponseBody
@RequestMapping(value = "forget_get_question.do",method = RequestMethod.POST)
public ServerResponse<String> forgetGetQuestion(String username){
return iUserService.forgetGetQuestion(username);
}
//忘记密码:第二步,检测问题的答案,返回token
@ResponseBody
@RequestMapping(value = "forget_checked_answer.do",method = RequestMethod.POST)
public ServerResponse<String> forgetCheckedAnswer(String username,String question,String answer){
return iUserService.forgetCheckedAnswer(username, question, answer);
}
//忘记密码:第三步,重置密码
@ResponseBody
@RequestMapping("forget_rest_password.do")
public ServerResponse<String> forgetRestPassword(String username,String password,String token){
return iUserService.forgetRestPassword(username, password, token);
}
}
4.用户管理模块接口(service)
package com.mall.service.impl;
import com.mall.common.Const;
import com.mall.common.ServerResponse;
import com.mall.common.TokenCache;
import com.mall.dao.UserMapper;
import com.mall.pojo.User;
import com.mall.service.IUserService;
import com.mall.util.MD5Util;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service("iUserService")
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userMapper;
//校验用户名和密码
public ServerResponse<User> login(String username, String password){
int rowCount=userMapper.checkUsername(username);
if(rowCount==0){
return ServerResponse.createByErrorMsg("用户不存在");
}
//MD5
password= MD5Util.MD5EncodeUtf8(password);
User user = userMapper.checkUserPassword(username, password);
if(user==null){
return ServerResponse.createByErrorMsg("密码错误");
}
user.setPassword(StringUtils.EMPTY);
return ServerResponse.createBySuccess(user);
}
//校验用户名和邮箱,然后查用User到数据库
public ServerResponse<String> register(User user){
ServerResponse validResponse=this.checkedValid(user.getUsername(), Const.USERNAME);
if(!validResponse.isSuccess()){
return validResponse;
}
validResponse=this.checkedValid(user.getEmail(),Const.EMAIL);
if(!validResponse.isSuccess()){
return validResponse;
}
user.setRole(Const.Role.ROLE_CUSTOMER);
//MD5
user.setPassword(MD5Util.MD5EncodeUtf8(user.getPassword()));
int rowCount=userMapper.insert(user);
if(rowCount>0){
return ServerResponse.createBySuccessMsg("注册成功");
}
return ServerResponse.createByErrorMsg("注册失败");
}
//检查用户名和邮箱的有效性,校验成功则用户名密码不存在
public ServerResponse<String> checkedValid(String str,String type){
if(StringUtils.isBlank(type)){
return ServerResponse.createByErrorMsg("参数错误");
}
if(Const.USERNAME.equals(type)){
int rowCount=userMapper.checkUsername(str);
if(rowCount>0){
return ServerResponse.createByErrorMsg("用户已存在");
}
}
if(Const.EMAIL.equals(type)){
int rowCount=userMapper.checkEmail(str);
if(rowCount>0){
return ServerResponse.createByErrorMsg("邮箱已存在");
}
}
return ServerResponse.createBySuccessMsg("校验成功,用户名、邮箱不存在");
}
//检查用户和旧密码,更新新密码
public ServerResponse<User> restPassword(String username,String oldPassword,String newPassword){
User user=userMapper.checkUserPassword(username,MD5Util.MD5EncodeUtf8(oldPassword));
if(user==null){
return ServerResponse.createBySuccessMsg("旧密码错误");
}
user.setPassword(MD5Util.MD5EncodeUtf8(newPassword));
int rowCount=userMapper.updateByPrimaryKeySelective(user);
user.setPassword(StringUtils.EMPTY);
if(rowCount>0){
return ServerResponse.createBySuccess(user);
}
return ServerResponse.createByError();
}
//更新用户的个人信息
public ServerResponse<User> updateInformation(User updateUser){
int rowCount=userMapper.checkEmailByUserId(updateUser.getEmail(),updateUser.getId());
if(rowCount>0){
return ServerResponse.createByErrorMsg("email已存在");
}
User endUpdateUser=new User();
endUpdateUser.setId(updateUser.getId());
endUpdateUser.setUsername(updateUser.getUsername());
endUpdateUser.setEmail(updateUser.getEmail());
endUpdateUser.setQuestion(updateUser.getQuestion());
endUpdateUser.setAnswer(updateUser.getAnswer());
rowCount=userMapper.updateByPrimaryKeySelective(endUpdateUser);
if (rowCount>0){
return ServerResponse.createBySuccess("更新个人信息成功",endUpdateUser);
}
return ServerResponse.createByErrorMsg("更新用户信息失败");
}
//使用用户名获取问题,将问题返回给前端
public ServerResponse<String> forgetGetQuestion(String username){
ServerResponse validResponse=this.checkedValid(username,Const.USERNAME);
if(validResponse.isSuccess()){
return ServerResponse.createByErrorMsg("该用户不存在");
}
String question=userMapper.checkQuestionByUsername(username);
if(StringUtils.isNotBlank(question)){
return ServerResponse.createBySuccess(question);
}
return ServerResponse.createBySuccessMsg("找回密码的问题是空的");
}
//检查问题的答案是否正确,设置token并返回给前端
public ServerResponse<String> forgetCheckedAnswer(String username,String question,String answer){
int rowCount=userMapper.checkAnswerByUsernameAndQuestion(username,question,answer);
if(rowCount==0){
return ServerResponse.createByErrorMsg("问题答案错误");
}
//设置token:问题的答案的有效时间
//key:"token_"+username value:forgetToken
String token= UUID.randomUUID().toString();
TokenCache.setKey(TokenCache.TOKEN_PREFIX+username,token);
return ServerResponse.createBySuccess("问题答案校验成功",token);
}
//检测用户名和token,检测token是否正确,更新密码
public ServerResponse<String> forgetRestPassword(String username,String password,String token){
ServerResponse response=this.checkedValid(username,Const.USERNAME);
if(response.isSuccess()){
ServerResponse.createByErrorMsg("该用户不存在");
}
if(StringUtils.isBlank(token)){
return ServerResponse.createByErrorMsg("Token无效过着过期");
}
if(TokenCache.getKey(TokenCache.TOKEN_PREFIX+username).equals(token)){
int rowCount=userMapper.updatePasswordByUsername(username,MD5Util.MD5EncodeUtf8(password));
if(rowCount>0){
return ServerResponse.createBySuccessMsg("密码重置成功");
}
return ServerResponse.createByErrorMsg("密码重置失败");
}
return ServerResponse.createByErrorMsg("Token错误,重置密码失败");
}
public ServerResponse<String> checkUserRole(User user){
if(user != null && user.getRole()==Const.Role.ROLE_ADMIN){
return ServerResponse.createBySuccess("用户是管理员,登陆成功");
}
return ServerResponse.createByErrorMsg("用户不是管理员,登陆失败");
}
}
5.用户管理模块(xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mall.dao.UserMapper" >
<resultMap id="BaseResultMap" type="com.mall.pojo.User" >
<constructor >
<idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="username" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="password" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="email" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="phone" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="question" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="answer" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="role" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, username, password, email, phone, question, answer, role, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from mmall_user
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from mmall_user
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.mall.pojo.User" >
insert into mmall_user (id, username, password,
email, phone, question,
answer, role, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
#{email,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{question,jdbcType=VARCHAR},
#{answer,jdbcType=VARCHAR}, #{role,jdbcType=INTEGER}, now(),
now())
</insert>
<insert id="insertSelective" parameterType="com.mall.pojo.User" >
insert into mmall_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="username != null" >
username,
</if>
<if test="password != null" >
password,
</if>
<if test="email != null" >
email,
</if>
<if test="phone != null" >
phone,
</if>
<if test="question != null" >
question,
</if>
<if test="answer != null" >
answer,
</if>
<if test="role != null" >
role,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="updateTime != null" >
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="username != null" >
#{username,jdbcType=VARCHAR},
</if>
<if test="password != null" >
#{password,jdbcType=VARCHAR},
</if>
<if test="email != null" >
#{email,jdbcType=VARCHAR},
</if>
<if test="phone != null" >
#{phone,jdbcType=VARCHAR},
</if>
<if test="question != null" >
#{question,jdbcType=VARCHAR},
</if>
<if test="answer != null" >
#{answer,jdbcType=VARCHAR},
</if>
<if test="role != null" >
#{role,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
now(),
</if>
<if test="updateTime != null" >
now(),
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.mall.pojo.User" >
update mmall_user
<set >
<if test="username != null" >
username = #{username,jdbcType=VARCHAR},
</if>
<if test="password != null" >
password = #{password,jdbcType=VARCHAR},
</if>
<if test="email != null" >
email = #{email,jdbcType=VARCHAR},
</if>
<if test="phone != null" >
phone = #{phone,jdbcType=VARCHAR},
</if>
<if test="question != null" >
question = #{question,jdbcType=VARCHAR},
</if>
<if test="answer != null" >
answer = #{answer,jdbcType=VARCHAR},
</if>
<if test="role != null" >
role = #{role,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
update_time = now(),
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.mall.pojo.User" >
update mmall_user
set username = #{username,jdbcType=VARCHAR},
password = #{password,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR},
phone = #{phone,jdbcType=VARCHAR},
question = #{question,jdbcType=VARCHAR},
answer = #{answer,jdbcType=VARCHAR},
role = #{role,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
<select id="checkUsername" parameterType="string" resultType="int">
select COUNT(1) from mmall_user where username = #{username}
</select>
<select id="checkEmail" parameterType="string" resultType="int">
select count(1) from mmall_user where email=#{email}
</select>
<select id="checkUserPassword" parameterType="map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from mmall_user
where username = #{username} and password=#{password}
</select>
<select id="checkEmailByUserId" parameterType="map" resultType="int">
select count(1) from mmall_user where id=#{userId} and email=#{email}
</select>
<select id="checkQuestionByUsername" parameterType="string" resultType="string">
select question from mmall_user where username=#{username}
</select>
<select id="checkAnswerByUsernameAndQuestion" parameterType="map" resultType="int">
select count(1) from mmall_user where username=#{username} and question=#{question} and answer=#{answer}
</select>
<update id="updatePasswordByUsername" parameterType="map">
update mmall_user
set password=#{password},update_time=now()
where username=#{username}
</update>
</mapper>
网友评论