登录注册——后端实现
任务
小组项目的框架基本搭建完整、工具类封装完好。
本次任务是实现登录注册的后端逻辑,为前端提供可用的接口。
具体工作
- 首先在UserService中
定义了一个名为 的接口,它继承自 接口,表示这个服务接口操作的是 类型的数据。
接口中定义了三个方法:
Integer Login(String userAccount, String userPassword):该方法用于用户登录逻辑,接收用户账号和密码作为参数,并返回一个整数值,可能用于表示登录成功与否的状态码或其他相关信息。
Integer ExistAccount(String userAccount):该方法用于判断用户是否存在,接收用户账号作为参数,并返回一个整数值,可能用于表示用户是否存在的状态码或其他相关信息。
long Register(User user):该方法用于用户注册逻辑,接收一个 对象作为参数,并返回一个长整型值,可能用于表示注册成功后的用户ID或其他相关信息。
import com.example.demo.model.User;
public interface UserService extends IService<User> {
//登录逻辑
Integer Login(String userAccount, String userPassword);
//判断用户是否存在
Integer ExistAccount(String userAccount);
//注册逻辑
long Register(User user);
}
-
在UserServiceImpl中进行逻辑的实现
Login 方法:该方法接收用户账号和密码作为参数,然后使用 MyBatis Plus 的查询条件进行数据库查询。
如果找不到匹配的用户,返回状态码 404 表示用户不存在。
如果找到了用户,返回状态码 200 表示登录成功。
ExistAccount 方法:该方法用于判断用户是否存在。
同样使用 MyBatis Plus 的查询条件进行数据库查询,根据用户账号查找用户。
如果找不到用户,返回状态码 1 表示用户不存在。
如果找到了用户,返回状态码 0 表示用户存在。
Register 方法:该方法接收一个用户对象作为参数,然后将用户信息保存到数据库中。
使用 将用户信息保存到数据库,并且返回用户的 ID。package com.example.demo.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.mapper.UserMapper; import com.example.demo.model.User; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; import java.util.Date; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { //继承了基本的逻辑,可以在此处添加其他逻辑 //登录 public Integer Login(String userAccount, String userPassword){ // 查询用户是否存在 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("userAccount", userAccount); queryWrapper.eq("userPassword", userPassword); User user = this.baseMapper.selectOne(queryWrapper); // 用户不存在返回状态码404 if (user == null) { return 404; } // 3.登录成功返回状态码200 return 200; } //判断用户是否存在 public Integer ExistAccount(String userAccount){ //使用Mybatis中的查找工具进行查找 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("userAccount", userAccount); User user = this.baseMapper.selectOne(queryWrapper); //没有找到 if(user == null){ return 1; } //找到了 return 0; } //注册 public long Register(User user){ //将用户信息保存到数据库中,并返回用户的Id this.save(user); return user.getId(); } }
-
在UserController
userLogin: 这个方法处理用户登录请求。它首先检查请求中是否包含了正确的数据,然后尝试使用用户提供的用户名和密码进行登录。如果登录成功,它会生成一个JWT token,并将其放入响应中返回给客户端。如果登录失败,则返回相应的错误信息。userLogout: 这个方法处理用户登出请求。在实际应用中,登出操作通常会导致当前的访问令牌失效,但是在你的代码中并没有实际执行这个操作。你可以在这个方法中添加相应的逻辑来使当前令牌失效。
userRegister: 这个方法处理用户注册请求。它从请求中获取用户提供的用户名、密码和电子邮件地址,并检查用户名是否已经存在。如果用户名已经存在,就返回相应的错误信息。如果用户名不存在,就创建一个新的用户对象,并将其保存到数据库中。最后,返回注册成功的消息以及新用户的ID。
package com.example.demo.controller; import com.auth0.jwt.interfaces.Claim; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.example.demo.model.User; import com.example.demo.payload.DataRequest; import com.example.demo.payload.DataResponse; import com.example.demo.service.UserService; import com.example.demo.utils.CommonMethod; import com.example.demo.utils.JwtUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; @RestController @RequestMapping("/api/user") public class UserController { @Autowired private UserService userService; @PostMapping("/login") public DataResponse userLogin(@RequestBody DataRequest dataRequest) { if (dataRequest == null) { return CommonMethod.getReturnData(400,"参数错误"); } /* *注意测试时的数据需要外层有个data{} */ String userAccount = dataRequest.getString("userAccount"); String password = dataRequest.getString("password"); if(userService.Login(userAccount,password)==200){ User user = new User(); user.setUserAccount(userAccount); user.setUserPassword(password); String token = JwtUtil.createToken(user);//token中有userAccount与password Map<String, String> data = new HashMap<>(); data.put("token",token); return CommonMethod.getReturnData(200,data,"登录成功"); }else{ return CommonMethod.getReturnData(400,"登录失败"); } } @PostMapping("/logout") public DataResponse userLogout(){ /* *此处应该有重置token的操作 */ return CommonMethod.getReturnData(200,null,"退出成功"); } @PostMapping("/register") public DataResponse userRegister(@RequestBody DataRequest dataRequest){ /* 注意前端传回来的数据格式需要正确 */ String userAccount=dataRequest.getString("userAccount"); String password=dataRequest.getString("password"); String email=dataRequest.getString("email"); //判断用户名是否重复 if(userService.ExistAccount(userAccount)==0){ return CommonMethod.getReturnData(400,"用户名重复"); } Date now =new Date(); User user=new User(); user.setUserPassword(password); user.setUserAccount(userAccount); user.setEmail(email); user.setCreateTime(now); //存入数据库,返回userId long userId=userService.Register(user); return CommonMethod.getReturnData(200,userId,"注册成功!"); } }
-
接口测试
登录接口测试:
注册接口用户名重复测试:
注册接口成功测试:
注册数据库插入成功测试:
结论与分析:
登录过程中,密码似乎是以明文形式进行传输和处理的。应该使用安全的加密算法来存储和验证密码,例如使用哈希算法加密密码,而不是将密码以明文形式存储在数据库中。
在生成 JWT token 时,要确保使用安全的方式进行签名和验证,并采取适当的措施来保护 token 的安全性,例如设置合适的过期时间、使用 HTTPS 进行传输等。
目前的实现中在某些情况下直接返回了固定的 HTTP 状态码和错误消息,例如在参数错误或登录失败时。更好的做法是使用异常处理机制,捕获并处理各种可能发生的异常,并返回具有适当错误码和消息的响应。
在用户注册时,没有对输入数据进行完整性验证。例如,可以添加对用户名、密码和电子邮件格式的验证,以确保它们符合预期的格式和长度要求。
对于用户注册后的流程,可能需要发送确认邮件或短信,以确保用户提供的电子邮件地址是有效的,并且用户确实希望注册。