注册接口
实现思路
1.特殊字段检查(比如性别没有给出需要给出默认值)
2.对比检查两次输入的密码是否一致,不一致报错
3.利用UUID生成随机‘盐’值,并使用密码进行MD5加密后与‘盐’进行拼接,生成加密后的密码
4.创建User对象并在数据库中查询该User对象是否存在,存在则报错
5.补充User对象的其他信息(文章数量、用户状态、用户删除状态、注册时间等)
6.使用insert方法将用户写入数据库,返回方法执行结果
实例代码
Contorller
@PostMapping("/register")
@ApiOperation("注册新用户(普通)的方法")public AppResult register(@RequestParam("username")@NonNull @ApiParam(value = "用户名") String username, @RequestParam("nickname")@NonNull @ApiParam(value = "昵称") String nickname, @RequestParam(value = "gender",required = false)@ApiParam(value = "性别") Byte gender , @RequestParam("password")@NonNull @ApiParam(value = "密码") String password, @RequestParam("passwordRepeat") @NonNull @ApiParam(value = "确认密码") String passwordRepeat){//测试数据的有效性if(gender==null||gender<0||gender>2){//如果错误,我们将性别信息进行清空gender=2;}//判断密码和确认密码是否相同if(!password.equals(passwordRepeat)){log.error(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME));}//对密码进行加密String salt = UUIDUtils.UUID_32();String newPassword = MD5Utils.md5Salt(password, salt);//将所有字段信息储存User user = new User();user.setUsername(username);user.setNickname(nickname);user.setGender(gender);user.setPassword(newPassword);user.setSalt(salt);userService.createCommonUser(user);return AppResult.success("用户新增成功!");}
Service
public void createCommonUser(User user) {//空指针排除if(user==null){//日志记录错误信息log.error("输入的用户信息不存在");throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}//从数据库中查询是否存在该数据User checkUser = userMapper.selectByUsername(user.getUsername());//存在抛出并记录日志/if(checkUser !=null){//记录日志log.error(ResultCode.FAILED_USER_EXISTS.toString()+"name="+checkUser.getUsername());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode. FAILED_USER_EXISTS));}//不存在则填充并插入数据,之后返回结果//补充结果if(user.getGender()==null) {//设置默认的性别user.setGender((byte) 2);}//设置其他值//设置发帖数量user.setPhoneNum("");user.setArticleCount(0);//设置是否为管理员user.setIsAdmin((byte) 0);//设置状态user.setState((byte) 0);//设置是否删除user.setDeleteState((byte) 0);//设置创建时间Date date = new Date();user.setCreateTime(date);user.setUpdateTime(date);//查看返回结果int result = userMapper.insertSelective(user);log.info("result="+result);if(result!=1){//记录错误日志log.error(ResultCode.FAILED_CREATE.toString());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));}//最终记录成功日志log.info("注册用户成功:"+user.getUsername());}
登录接口
实现思路
1.使用@NonNull注解确保账号密码不为空
2.从数据库中查询是否存在该数据,如果不存在直接报错
3.从数据库中取出对应数据的‘盐’值,使用输入用户对应的密码进行MD5加密后使用该‘盐’进行拼接,之后与数据库中的密码进行比对是否相等,不相等直接报错
4.登录成功后建立对应的session,并设置session对应的属性作为我们后续检查是否登录的依据(session.setAttribute(AppConfig.USER_SESSION, loginUser)
实例代码
Controller
@ApiOperation("登录方法")@PostMapping("/login")public AppResult login(HttpServletRequest request, @ApiParam(value = "用户名") @RequestParam(value = "username")@NonNull String username, @ApiParam(value = "密码")@RequestParam(value = "password")@NonNull String password){//调用service登录方法User loginUser = userService.login(username, password);//存储sessionHttpSession session=request.getSession(true);session.setAttribute(AppConfig.USER_SESSION, loginUser);//返回结果return AppResult.success("登录成功",loginUser);}
Service
@Overridepublic User login(String username, String password) {//判断账号密码是否为空if(StringUtils.isEmpty(username)&&StringUtils.isEmpty(password)){//打印错误的日志信息log.error(ResultCode.ERROR_IS_NULL.toString());//抛出异常throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}//从数据库中查询数据User user = selectByUsername(username);if(user==null){//记录日志并抛出异常//数据库中没有该用户记录则直接报错//为了提高数据库的安全性,即使用户不存在,我们也返回账号或密码错误log.error(ResultCode.FAILED_LOGIN.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));}//查询到比对密码String truePassword=user.getPassword();//对密码进行md5加密String repeatPassword= MD5Utils.md5Salt(password, user.getSalt());if(!repeatPassword.equals(truePassword)){//记录错误日志log.error(ResultCode.FAILED_LOGIN.toString());//密码错误返回报错信息throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));}//密码相同登陆成功,返回用户信息log.info("用户登录成功!");return user;}
退出登录接口
实现思路
1.通过HttpServletRequest获取session对象
2.将session对象中将我们此前设置的属性值去除
3.将我们设置的session对象设置无效化(invalidate),并进行页面跳转
实例代码
controller
@ApiOperation("用户退出方法")@GetMapping("/logout")public AppResult logout(HttpServletRequest request){//检查session是否有效HttpSession session = request.getSession(false);if(session==null){//记录错误日志log.error(ResultCode.USER_NOT_LOG.toString());//返回错误信息throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}//去除sessionObject user = session.getAttribute(AppConfig.USER_SESSION);log.info("用户退出"+user);session.invalidate();//返回结果return AppResult.success("用户退出成功.");}
查看用户信息接口
实现思路
1.根据前端传来的参数中是否包括id来判断当前需要显示的信息是对应文章的作者信息还是当前登录的用户信息
2.如果是当前登录的用户,直接在session中根据键获取对应的值(当前登录的用户),将这个信息直接返回给前端即可
3.如果是对应文章的用户,我们需要根据主键从数据库中查询信息并将该信息返回
实例代码
controller
@GetMapping("/info")@ApiOperation("展示用户信息的方法")public AppResult userInfo(HttpServletRequest request ,@ApiParam(value = "用户id")@RequestParam(value = "id" ,required = false) Long id){//判断是否存在id//不存在id返回当前登录的用户信息if(id==null){//获取sessionHttpSession session = request.getSession(false);//session为null说明用户未登录if(session==null){//记录错误日志log.error(ResultCode.USER_NOT_LOG.toString());//返回错误信息throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}User user = (User)session.getAttribute(AppConfig.USER_SESSION);if(user==null){//记录错误日志log.error(ResultCode.USER_NOT_LOG.toString());//返回错误信息throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}return AppResult.success("用户查询成功!",user);}//存在id返回指定id的用户else{User user = userService.selectByPrimaryKey(id);if(user==null){log.error(ResultCode.FAILED_USER_NOT_EXISTS.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}return AppResult.success("用户查询成功",user);}}
service
@Overridepublic User selectByPrimaryKey(Long id) {//判断id是否为空if(id==null){log.error(ResultCode.ERROR_IS_NULL.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}//调用方法return userMapper.selectByPrimaryKey(id);}
修改用户信息接口
实现思路
1.通过当前session获取当前登录的用户与需要修改信息的用户id进行比对判断是否有权进行信息的修改
2.有权进行休息的修改则调用service进行信息的修改,其中在service中对需要修改的字段进行设置,最后调用mapper对应的selective方法进行数据处理
实例代码
controller
@ApiOperation("修改用户个人信息的方法!")@PostMapping("/modify")public AppResult modifyInfo (HttpServletRequest request,@ApiParam("用户Id") @RequestParam("id") @NonNull Long id,@ApiParam("性别") @RequestParam(value = "gender", required = false) Byte gender,@ApiParam("昵称") @RequestParam(value = "nickname", required = false) String nickname,@ApiParam("电话号码") @RequestParam(value = "phoneNum", required = false) String phoneNum,@ApiParam("邮箱") @RequestParam(value = "email", required = false) String email,@ApiParam("个人简介") @RequestParam(value = "remark", required = false) String remark) {// 校验if (gender == null&& StringUtils.isEmpty(nickname)&& StringUtils.isEmpty(phoneNum)&& StringUtils.isEmpty(email)&& StringUtils.isEmpty(remark)) {// 参数同时为空时返回错误信息return AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE.toString());}// 校验传入的Id是否为当前登录用户HttpSession session = request.getSession();User user = (User) session.getAttribute(AppConfig.USER_SESSION);if (user.getId() != id) {// 返回错误return AppResult.failed(ResultCode.FAILED_UNAUTHORIZED.toString());}// 调用serviceuserService.modifyInfo(id, gender, nickname, phoneNum, email, remark);// 重新获取用户信息,更新sessionuser = userService.selectByPrimaryKey(id);session.setAttribute(AppConfig.USER_SESSION, user);// 返回结果return AppResult.success();
service
@Overridepublic void modifyInfo(Long id, Byte gender, String nickname, String phoneNum, String email, String remark) {// 非空校验,id为null 或 其他的参数全部为nullif (id == null || (gender == null&& StringUtils.isEmpty(nickname)&& StringUtils.isEmpty(phoneNum)&& StringUtils.isEmpty(email)&& StringUtils.isEmpty(remark))) {log.warn(ResultCode.ERROR_IS_NULL.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_IS_NULL));}// 校验用户状态User user = userMapper.selectByPrimaryKey(id);if (user == null || user.getDeleteState() == 1) {log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}// 构造一个修改对象User updateUser = new User();// 设置IdupdateUser.setId(id);// 设置昵称if (!StringUtils.isEmpty(nickname)) {updateUser.setNickname(nickname);}// 设置电话if (!StringUtils.isEmpty(phoneNum)) {updateUser.setPhoneNum(phoneNum);}// 设置邮箱if (!StringUtils.isEmpty(email)) {updateUser.setEmail(email);}// 个人简介if (!StringUtils.isEmpty(remark)) {updateUser.setRemark(remark);}// 性别if (gender != null && gender >= 0 && gender <= 2) {updateUser.setGender(gender);}// 调用DAOint row = userMapper.updateByPrimaryKeySelective(updateUser);if (row != 1) {log.warn(ResultCode.ERROR_UPDATE.toString());throw new ApplicationException(AppResult.failed(ResultCode.ERROR_UPDATE));}}
修改密码接口
实现思路
1.通过session获得当前登录的用户,并判断是否有权修改对应id用户的密码(id是否相等)
2.判断输入的新密码和重复密码是否相等
3.进入service通过id从数据库中查看并判断当前用户是否存在
4.获取对应用户的salt并使用md5对输入的原密码加密并与之拼接后再与数据库中的原密码进行比对,判断输入的原密码是否正确
5.上述比对全部通过之后生成新的salt,将密码加密后进行存储
实例代码
controller
@ApiOperation("修改密码的方法")
@PostMapping("/modifyPwd")public AppResult modifyPassword(HttpServletRequest request,@NonNull@RequestParam(value = "id")@ApiParam(value = "用户id") Long id,@NonNull@RequestParam("oldPassword")@ApiParam(value = "用户的旧密码") String oldPassword,@NonNull@RequestParam("newPassword")@ApiParam(value = "新密码") String newPassword,@NonNull @RequestParam("passwordRepeat")@ApiParam(value = "重复密码") String passwordRepeat){//判断当前用户是否登录,没有登录直接报错HttpSession session = request.getSession(false);if(session==null){log.error(ResultCode.USER_NOT_LOG.toString());throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}User loginUser =(User) session.getAttribute(AppConfig.USER_SESSION);if(loginUser==null){log.error(ResultCode.USER_NOT_LOG.toString());throw new ApplicationException(AppResult.failed(ResultCode.USER_NOT_LOG));}//登录之后判断当前用户是否有权修改密码//无权直接报错if(loginUser.getId()!=id){log.error(ResultCode.FAILED_UNAUTHORIZED.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_UNAUTHORIZED));}//判断两次密码是否一致if(!newPassword.equals(passwordRepeat)){//密码不一致进行报错log.error(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());throw new ApplicationException(AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME));}//密码一致则进行修改信息userService.modifyPassword(id, oldPassword, newPassword, passwordRepeat);log.info("密码修改成功,"+loginUser.getUsername());return AppResult.success("密码修改成功");}
service
public void modifyPassword(Long id, String oldPassword, String newPassword, String passwordRepeat) {//判断id对应的用户是否存在User checkUser = userMapper.selectByPrimaryKey(id);//用户不存在直接报错if(checkUser==null){//记录错误信息log.error(ResultCode.FAILED_USER_NOT_EXISTS.toString());//进行报错throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));}//如果用户存在更新信息//判断原密码和输入的原密码是否相同,不相同直接报错//对输入的密码进行加密String oldSalt = checkUser.getSalt();String realOldPassword = MD5Utils.md5Salt(oldPassword, oldSalt);if(!realOldPassword.equals(checkUser.getPassword())){log.error(ResultCode.FAILED_PASSWORD.toString());//报错throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PASSWORD));}//如果相同继续修改//创建对象并修改User user = new User();//生成加密字符String salt = UUIDUtils.UUID_32();//进行密码加密String realPassword = MD5Utils.md5Salt(newPassword, salt);//将salt存入user.setSalt(salt);user.setPassword(realPassword);user.setId(id);//修改个人信息int result = userMapper.updateByPrimaryKeySelective(user);if(result!=1){log.error(ResultCode.ERROR_UPDATE.toString());AppResult.failed(ResultCode.ERROR_UPDATE);}//生成修改成功的日志log.info("用户密码修改成功!" );}