注册接口
实现思路
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);
//存储session
HttpSession session=request.getSession(true);
session.setAttribute(AppConfig.USER_SESSION, loginUser);
//返回结果
return AppResult.success("登录成功",loginUser);
}
Service
@Override
public 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));
}
//去除session
Object 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){
//获取session
HttpSession 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
@Override
public 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());
}
// 调用service
userService.modifyInfo(id, gender, nickname, phoneNum, email, remark);
// 重新获取用户信息,更新session
user = userService.selectByPrimaryKey(id);
session.setAttribute(AppConfig.USER_SESSION, user);
// 返回结果
return AppResult.success();
service
@Override
public void modifyInfo(Long id, Byte gender, String nickname, String phoneNum, String email, String remark) {
// 非空校验,id为null 或 其他的参数全部为null
if (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();
// 设置Id
updateUser.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);
}
// 调用DAO
int 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("用户密码修改成功!" );
}