9. 实现业务功能--用户登录

目录

1. 顺序图 

2. 参数要求

3. 创建 Service 接口

4. 实现 Service 接口

5. 单体测试

6. 实现 Controller 

7. 实现前端


在用户登录部分特别注意的是需要进行密码校验:

1. MD5(MD5(用户提交的原密码)+数据库查出来的用户的盐)= 密码的密文

2. 用上面的生成的密码的密文和数据库中用户的 password 字段的密码作比较,如果相等,则校验通过,否则失败。

1. 顺序图 

9. 实现业务功能--用户登录_第1张图片

2. 参数要求

登录时需要用户提交的参数列表:

参数名 描述 类型 默认值 条件
username 用户名 String 必须
password 密码 String 必须

3. 创建 Service 接口

根据用户名查询用户信息:

public interface IUserService {
    /**
     * 根据用户名查询用户信息
     * @param username 用户名
     * @return
     */
    User selectByName(String username);

    /**
     * 创建普通用户
     *
     * @param user 用户名
     */
    void createNormalUser(User user);

    /**
     * ⽤⼾登录
     * @param username ⽤⼾名
     * @param password 密码
     * @return
     */
    User login(String username, String password);
}

4. 实现 Service 接口

@Slf4j // 日志
@Service // 交给 Spring 管理
public class UserServiceImpl implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public User selectByName(String username) {
        // 非空校验
        if(StringUtils.isEmpty(username)){
            // 打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 根据用户名查询用户信息
        User user = userMapper.selectByName(username);
        // 返回结果
        return user;
    }

    @Override
    public void createNormalUser(User user) {
        // 非空校验
        if(user == null || StringUtils.isEmpty(user.getUsername())
                || StringUtils.isEmpty(user.getNickname())
                || StringUtils.isEmpty(user.getPassword())
                || StringUtils.isEmpty(user.getSalt())){
            // 打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 校验用户是否存在
        User existUser = selectByName(user.getUsername());
        if(existUser != null){
            // 打印日志
            log.warn(ResultCode.FAILED_USER_EXISTS.toString() + "username = " + user.getUsername());
            // 抛出异常,用户已存在
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
        }
        // 为属性设置默认值
        // 性别 0女 1男 2保密
        if(user.getGender() != null){
            if(user.getGender() < 0 || user.getGender() > 2){
                user.setGender((byte)2);
            }
        }else{
            user.setGender((byte)2);
        }
        // 发帖数
        user.setArticleCount(0);
        // 是否管理员
        user.setIsAdmin((byte)0);
        // 状态
        user.setState((byte)0);
        // 时间
        Date date = new Date();
        user.setCreateTime(date); // 创建时间
        user.setUpdateTime(date); // 更新时间

        // 写入数据库
        int row = userMapper.insertSelective(user);
        if(row != 1){
            // 打印日志
            log.warn(ResultCode.FAILED_CREATE.toString() + "注册用户失败,username = " + user.getUsername());
            // 抛出异常,用户已存在
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
    }

    @Override
    public User login(String username, String password) {
        // 非空校验
        if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
            // 打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            // 抛出异常,用户已存在
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        // 根据用户名查询用户信息
        User user = selectByName(username);
        // 校验用户是否存在
        if (user == null) {
            // 打印日志
            log.info(ResultCode.FAILED_USER_NOT_EXISTS.toString()+",username = " + username);
            // 抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        // 校验密码是否正确
        String encryptPassword = MD5Utils.md5Salt(password, user.getSalt());
        if (!encryptPassword.equalsIgnoreCase(user.getPassword())) {
            // 打印日志
            log.info("密码输入错误,username = " + username + ", password = " + password);
            // 密码不正确抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN));
        }
        // 校验通过,返回用户信息
        return user;
    }
}

5. 单体测试

编写测试代码:

@Test
    void login() throws JsonProcessingException {
        // 正确用户
        User user = userService.login("Danny","123");
        System.out.println(objectMapper.writeValueAsString(user));

        // 错误用户
        user = userService.login("123","123");
        System.out.println(objectMapper.writeValueAsString(user));

    }

测试结果如下: 

6. 实现 Controller 

在 UserControlle r中实现登录方法:
9. 实现业务功能--用户登录_第2张图片

 因此在 Config 包下新建 AppConfig 类,添加全局变量:

public class AppConfig {
    /**
     * 为 session 中存储的 User 对象定义一个全局变量
     */
    public static final String SESSION_USER_KEY = "SESSION_USER_KEY";
}

继续编写 UserController 类中的方法:

/**
     * 用户登录
     *
     * @param request
     * @param username 用户名
     * @param password 密码
     * @return AppResult
     */
    @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 user = userService.login(username, password);
        // 在 session 中保存当前登录的用户信息
        // 1. 获取 session 对象
        HttpSession session = request.getSession(true);
        // 2. 把用户信息保存在 session 中
        session.setAttribute(AppConfig.SESSION_USER_KEY, user);
        // 登录成功响应
        return AppResult.success("登录成功");
    }
启动程序,访问 API 页面 login 接口,分别提交错误和正确的用户名密码进行测试:
登录失败:

9. 实现业务功能--用户登录_第3张图片

 登陆成功:

9. 实现业务功能--用户登录_第4张图片

7. 实现前端

完整的前端代码:forum: 论坛项目 - Gitee.com

// 构造数据
        let postData = {
          username : $('#username').val(),
          password : $('#password').val()
        };
        // 发送AJAX请求,成功后跳转到index.html
        $.ajax({
          // 请求的方法类型
          type : 'POST',
          // API 的 URL
          url : 'user/login',
          //数据格式
          contentType : 'application/x-www-form-urlencoded',
          // 提交的数据
          data : postData,
          // 成功回调
          success : function(respData) {
          // ⽤状态码判断是否成功
            if (respData.code == 0) {
              // 成功
              location.assign('index.html');
            } else {
            // 失败
            $.toast({
              heading : '警告',
              text : respData.message,
              icon : 'Warning'
            });
           }
          },
          // 失败(HTTP)
          error: function() {
            $.toast({
              heading : '错误',
              text : '出错了,请联系管理员',
              icon : 'error'
            });
          }
        });
      });

登录后的界面如下: 

9. 实现业务功能--用户登录_第5张图片


以上即为登录功能的实现,接下来在下篇博客中我们将实现在上面登录进去的界面中进行退出。

你可能感兴趣的:(项目,数据库,服务器,运维)