4.对密码进行MD5保护
我们新建一个包util,是专门用来存放工具的包。里面创建一个类MD5Utils
package com.haiexijun.mall.util; import com.haiexijun.mall.common.Constant; import org.apache.tomcat.util.codec.binary.Base64; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * 描述:MD5加密工具 */ public class MD5Utils { public static String GetMD5String(String strValue) throws NoSuchAlgorithmException { // Java为我们提供了MD5算法 MessageDigest md5=MessageDigest.getInstance("MD5"); //Base64用tomcat提供的 return Base64.encodeBase64String(md5.digest((strValue+ Constant.SALT).getBytes())); } public static void main(String[] args) { try { System.out.println(GetMD5String("123456")); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } }
我们直接这样加密其实很容易就能破解出来,所以要加一个盐值,上面我们也用到了盐值,它存放在了common包下面的Constant常量类中:
package com.haiexijun.mall.common; /** * 描述: 常量类 */ public class Constant { public static final String SALT="fb?rh=jh[v!ur';/~2``>"; }
然后在UserServiceImpl类中,对密码加密进行调用:
try { user.setPassword(MD5Utils.GetMD5String(password)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
到这里,就完成了注册接口的开发。
5.登录、登出、更新接口的开发
登录需要对登录的状态进行保存的,保存登录状态就要用到session。服务端把用户信息保存到session里面,以后用户还想来我们系统进行访问的话,我们就可以通过session把用户识别出来。登出的话就是把session的MALL_USER给移除掉就行。下面对整个用户模块的代码一次性列出好了。
UserController:
package com.haiexijun.mall.controller; import com.haiexijun.mall.common.ApiRestResponse; import com.haiexijun.mall.common.Constant; import com.haiexijun.mall.exception.MallException; import com.haiexijun.mall.exception.MallExceptionEnum; import com.haiexijun.mall.model.pojo.User; import com.haiexijun.mall.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpSession; /** * 描述:用户控制器 */ @Controller public class UserController { @Autowired UserService userService; //测试接口 @GetMapping("/test") @ResponseBody public User personalPage(){ return userService.getUser(); } //用户测试接口 @PostMapping("/register") @ResponseBody public ApiRestResponse register(@RequestParam("userName") String userName, @RequestParam("password") String password) throws MallException { //注册校验 //StringUtils是springboot提供的字符串判断类 if(StringUtils.isEmpty(userName)){ //如果用户名为空 return ApiRestResponse.error(MallExceptionEnum.NEED_USER_NAME) ; } if (StringUtils.isEmpty(password)){ //如果密码为空 return ApiRestResponse.error(MallExceptionEnum.NEED_USER_PASSWORD); } if (StringUtils.isEmpty(userName)&&StringUtils.isEmpty(password)){ //用户名和密码都为空 return ApiRestResponse.error(MallExceptionEnum.USER_NAME_AND_PASSWORD_IS_NULL); } if (password.length()<8){ //如果密码长度太小,也要报异常,这里为不小于八位 return ApiRestResponse.error(MallExceptionEnum.PASSWORD_TOO_SHORT); } //如果密码不小于八位,而且一切正常的话 userService.register(userName,password); return ApiRestResponse.success(); } //用户登录接口 @PostMapping("/login") @ResponseBody public ApiRestResponse login(@RequestParam("userName") String userName, @RequestParam("password") String password, HttpSession session) throws MallException { //登录校验 //StringUtils是springboot提供的字符串判断类 if(StringUtils.isEmpty(userName)){ //如果用户名为空 return ApiRestResponse.error(MallExceptionEnum.NEED_USER_NAME) ; } if (StringUtils.isEmpty(password)){ //如果密码为空 return ApiRestResponse.error(MallExceptionEnum.NEED_USER_PASSWORD); } if (StringUtils.isEmpty(userName)&&StringUtils.isEmpty(password)){ //用户名和密码都为空 return ApiRestResponse.error(MallExceptionEnum.USER_NAME_AND_PASSWORD_IS_NULL); } User user= userService.login(userName,password); //把密码返回做隐藏处理,更安全 user.setPassword("************"); session.setAttribute(Constant.MALL_USER,user); return ApiRestResponse.success(user); } //用户更新接口 @PostMapping("/user/update") @ResponseBody public ApiRestResponse updateUserInfo(HttpSession session,@RequestParam("signature") String signature) throws MallException { User currentUser= (User) session.getAttribute(Constant.MALL_USER); if(currentUser==null){ //如果为null,则该用户还没有登录 return ApiRestResponse.error(MallExceptionEnum.NEED_LOGIN); } //如果用户已经登录了 User user=new User(); user.setId(currentUser.getId()); user.setPersonalizedSignature(signature); userService.updateInformation(user); return ApiRestResponse.success(); } //用户登出接口 @PostMapping("user/logout") @ResponseBody public ApiRestResponse logout(HttpSession session){ session.removeAttribute(Constant.MALL_USER); return ApiRestResponse.success(); } //管理员登录接口 @PostMapping("/adminLogin") @ResponseBody public ApiRestResponse adminLogin(@RequestParam("userName") String userName, @RequestParam("password") String password, HttpSession session) throws MallException { //登录校验 //StringUtils是springboot提供的字符串判断类 if(StringUtils.isEmpty(userName)){ //如果用户名为空 return ApiRestResponse.error(MallExceptionEnum.NEED_USER_NAME) ; } if (StringUtils.isEmpty(password)){ //如果密码为空 return ApiRestResponse.error(MallExceptionEnum.NEED_USER_PASSWORD); } if (StringUtils.isEmpty(userName)&&StringUtils.isEmpty(password)){ //用户名和密码都为空 return ApiRestResponse.error(MallExceptionEnum.USER_NAME_AND_PASSWORD_IS_NULL); } User user= userService.login(userName,password); //校验是否未管理员 if (userService.checkAdminRole(user)) { //如果是管理员,就可以执行操作 //把密码返回做隐藏处理,更安全 user.setPassword("************"); session.setAttribute(Constant.MALL_USER,user); return ApiRestResponse.success(user); }else { //如果不是管理员 return ApiRestResponse.error(MallExceptionEnum.NEED_ADMIN); } } }
UserService:
package com.haiexijun.mall.service; import com.haiexijun.mall.exception.MallException; import com.haiexijun.mall.model.pojo.User; public interface UserService { public User getUser(); void register(String userName,String password) throws MallException; User login(String username, String password) throws MallException; void updateInformation(User user) throws MallException; boolean checkAdminRole(User user); }
UserServiceImpl:
package com.haiexijun.mall.service.impl; import com.haiexijun.mall.common.ApiRestResponse; import com.haiexijun.mall.exception.MallException; import com.haiexijun.mall.exception.MallExceptionEnum; import com.haiexijun.mall.model.dao.UserMapper; import com.haiexijun.mall.model.pojo.User; import com.haiexijun.mall.service.UserService; import com.haiexijun.mall.util.MD5Utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.security.NoSuchAlgorithmException; @Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Override public User getUser() { //测试用 return userMapper.selectByPrimaryKey(4); } @Override public void register(String userName, String password) throws MallException { //查询用户名是否存在,不允许重名 User result=userMapper.selectByName(userName); if (result !=null){ //如果重名就抛出异常,把它作为异常进行抛出去 throw new MallException(MallExceptionEnum.NAME_EXISTED); } //如果没有重名,就把注册的用户信息写到数据库中,注册成功 User user=new User(); user.setUsername(userName); try { user.setPassword(MD5Utils.GetMD5String(password)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } //userMapper的insertSelective方法会先判断插入数据的字段是否为空,如果不是空,才对他进行插入。insert方法则全部插入 //方法返回插入成功的条数 int count= userMapper.insertSelective(user); // 下面判断一下是否插入成功 if (count==0){ throw new MallException(MallExceptionEnum.INSERT_FAILED); } } @Override public User login(String username, String password) throws MallException { String md5Password=null; try { md5Password=MD5Utils.GetMD5String(password); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } User user=userMapper.selectLogin(username,password); if (user==null){ //如果查询结果为空的话,代表密码错误,抛出一个异常 throw new MallException(MallExceptionEnum.WRONG_PASSWORD); } return user; } @Override public void updateInformation(User user) throws MallException { //用于更新个性签名 int updateCount=userMapper.updateByPrimaryKeySelective(user); if (updateCount>1){ throw new MallException(MallExceptionEnum.UPDATE_FAILED); } } @Override public boolean checkAdminRole(User user){ //2是管理员 return user.getRole().equals(2); } }
UserMapper:
package com.haiexijun.mall.model.dao; import com.haiexijun.mall.model.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; @Repository public interface UserMapper { int deleteByPrimaryKey(Integer id); int insert(User record); int insertSelective(User record); User selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(User record); int updateByPrimaryKey(User record); User selectByName(String userName); //这里传入了两个以上的参数,要用到@para注解,一个参数则不用 User selectLogin(@Param("userName") String userName,@Param("password") String password); }
UserMapper.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.haiexijun.mall.model.dao.UserMapper"> <resultMap id="BaseResultMap" type="com.haiexijun.mall.model.pojo.User"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="username" jdbcType="VARCHAR" property="username" /> <result column="password" jdbcType="VARCHAR" property="password" /> <result column="personalized_signature" jdbcType="VARCHAR" property="personalizedSignature" /> <result column="role" jdbcType="INTEGER" property="role" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> </resultMap> <sql id="Base_Column_List"> id, username, `password`, personalized_signature, `role`, create_time, update_time </sql> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from mall_user where id = #{id,jdbcType=INTEGER} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> delete from mall_user where id = #{id,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.haiexijun.mall.model.pojo.User"> insert into mall_user (id, username, `password`, personalized_signature, `role`, create_time, update_time) values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{personalizedSignature,jdbcType=VARCHAR}, #{role,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}) </insert> <insert id="insertSelective" parameterType="com.haiexijun.mall.model.pojo.User"> insert into mall_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="personalizedSignature != null"> personalized_signature, </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="personalizedSignature != null"> #{personalizedSignature,jdbcType=VARCHAR}, </if> <if test="role != null"> #{role,jdbcType=INTEGER}, </if> <if test="createTime != null"> #{createTime,jdbcType=TIMESTAMP}, </if> <if test="updateTime != null"> #{updateTime,jdbcType=TIMESTAMP}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="com.haiexijun.mall.model.pojo.User"> update mall_user <set> <if test="username != null"> username = #{username,jdbcType=VARCHAR}, </if> <if test="password != null"> `password` = #{password,jdbcType=VARCHAR}, </if> <if test="personalizedSignature != null"> personalized_signature = #{personalizedSignature,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 = #{updateTime,jdbcType=TIMESTAMP}, </if> </set> where id = #{id,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="com.haiexijun.mall.model.pojo.User"> update mall_user set username = #{username,jdbcType=VARCHAR}, `password` = #{password,jdbcType=VARCHAR}, personalized_signature = #{personalizedSignature,jdbcType=VARCHAR}, `role` = #{role,jdbcType=INTEGER}, create_time = #{createTime,jdbcType=TIMESTAMP}, update_time = #{updateTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=INTEGER} </update> <select id="selectByName" parameterType="java.lang.String" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from mall_user where username=#{userName,jdbcType=VARCHAR} </select> <select id="selectLogin" parameterType="map" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from mall_user where username=#{userName,jdbcType=VARCHAR} and password=#{password,jdbcType=VARCHAR} </select> </mapper>
常量类Constant:
package com.haiexijun.mall.common; /** * 描述: 常量类 */ public class Constant { public static final String SALT="fb?rh=jh[v!ur';/~2``>"; public static final String MALL_USER="mall_user"; }
异常枚举类:
package com.haiexijun.mall.exception; /** * 描述类:异常枚举类 */ public enum MallExceptionEnum { NEED_USER_NAME(10001,"用户名不能为空"), PASSWORD_TOO_SHORT(10003,"密码长度不能小于八位"), NEED_USER_PASSWORD(10002,"用户密码不能为空"), NAME_EXISTED(10004,"用户名已存在,注册失败"), INSERT_FAILED(10005,"插入失败,请重试"), WRONG_PASSWORD(10007,"密码错误"), NEED_LOGIN(10008,"用户未登录"), USER_NAME_AND_PASSWORD_IS_NULL(10006,"用户名和密码不能为空"), UPDATE_FAILED(10009,"更新失败"), NEED_ADMIN(10010,"无管理员权限"), SYSTEM_ERROR(20000,"系统异常"); //异常码 Integer code; //异常信息 String msg; MallExceptionEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
到这里,我们用户模块就基本开发好了。