1.登录模块

登录模块主要实现的功能有:
① 登录功能: 用户输入学号,密码,验证码验证登录
② 用户登录日志: 用户登录成功后,将用户的学号,登录时间,ip地址存入数据库
一. 登录功能
  • 验证码模块实现的思想: 后台将生成验证码传给前端,并同时保存到session中, 用户输入学号,密码,验证码发送给后端, 后端取出session中的验证码进行对比,如果验证码错误,直接返回字符串"验证码错误", 如果验证码正确,继续查找是否存在该用户,如果存在, 返回"用户存在", 不存在返回 “用户不存在”

  • 以上就是我在做这个模块遇到的问题以及解决方案和参考的博客, 然后接下来就是代码部分

  • 后端代码一: 生成验证码

    package com.zhl.controller;
    
    import com.google.code.kaptcha.Constants;
    import com.google.code.kaptcha.Producer;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    import javax.imageio.ImageIO;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.awt.image.BufferedImage;
    
    /**
     * @author ZhangHailong
     * @date 2022/3/3 - 12:38
     * @project_name
     */
    @Controller
    @RequestMapping("/kaptcha")
    public class KaptchaController {
        @Autowired
        private Producer captchaProducer = null;
    
        @RequestMapping(value = "/getKaptchaImage.do")
        @CrossOrigin(allowCredentials="true")
        public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpSession session = request.getSession();
            response.setDateHeader("Expires", 0);
            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
            response.addHeader("Cache-Control", "post-check=0, pre-check=0");
            response.setHeader("Pragma", "no-cache");
            response.setContentType("image/jpeg");
            //生成验证码
            String capText = captchaProducer.createText();
            System.out.println("生成的验证码: " + capText);
            session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
    
            //向客户端写出
            BufferedImage bi = captchaProducer.createImage(capText);
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(bi, "jpg", out);
            try {
                out.flush();
            } finally {
                out.close();
            }
        }
    
    }
    
  • 后端代码二: 验证登录信息

       // 用户登录
    @RequestMapping(value = "/loginUser.do", method = RequestMethod.POST)
    @ResponseBody
    @CrossOrigin(allowCredentials="true")
    public String loginUserService(@RequestBody LoginUser loginUser, HttpServletRequest request) {
    
        System.out.println(loginUser);
    
        // 先判断验证码
        // 拿到session中的验证码的值
        String verifyCodeExepected = (String)request.getSession().getAttribute(
                com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
        System.out.println("session存储的:" + verifyCodeExepected);
        // 拿到提交的验证码
        String code = loginUser.getCode();
        System.out.println("提交的验证码:" + code);
    
        if(code != null && verifyCodeExepected.equalsIgnoreCase(code)) {
            // 验证码正确,继续验证登录
    
            User user = new User();
            user.setId(Integer.valueOf(loginUser.getId()));
            user.setPassword(loginUser.getPassword());
    
            // 将用户登录的ip作为loginUser的参数,以供切面拿取
            String ipAddress = request.getRemoteAddr();
    
            User userExist = userService.loginUser(user, ipAddress);
            if (userExist != null) {
    
                return "用户存在";
            }
    
            return "用户不存在";
    
        }
        return "验证码错误";
    
    }
    

    这里要说明的是,为什么loginUser有两个参数,实际上在做用户验证的时候只需要user这个参数就行了,它里面包含了用户的id和password,第二个参数ipAddress是为登录日志模块服务的,先按下不表,下面会解释

  • 前端

    handleSubmit(event) {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          this.loading = true;
          
          this.$http
          .post("http://localhost:8888/user/loginUser.do", this.loginForm,{withCredentials:true})
          .then((res) => {
            
            if (res.data == "用户存在") {
              
              this.loading = false;
              // localStorage.setItem("userId", this.loginForm.id);
              sessionStorage.setItem("userId", this.loginForm.id);
              this.$router.push({ path: "/" });
    
              // 显示登录成功的提示框
              this.$message({
                message: this.loginForm.id + ',登录成功',
                type: 'success'
              });
    
            } else if (res.data == "验证码错误") {
              
              this.loading = false;
              this.$alert("验证码错误", "提示", {
                confirmButtonText: "确认",
              });
              this.$refs.codeClickPosition.focus();
              this.loginForm.code = "";
    
            }
            else {
              
              this.loading = false;
              this.$alert("用户名或密码错误!", "提示", {
                confirmButtonText: "确认",
              });
              this.$refs.idClickPosition.focus();
            
            }
          });
    
        } else {
          console.log("error submit!");
          return false;
        }
      });
    },
    

    在这里,如果登录成功了,将用户的学号保存到session中,存这个学号的目的是,在用户登录成功以后,主页的右上角不是要显示他的头像和昵称还有其他信息嘛,所以想到时候用学号做一个查询,用的是sessionStorage而不是localStorage,具体的区别大家可以查看: sessionStorage和sessionStorage的区别, 我这里使用的是sessionStorage,用户在关闭网站后身份信息就清空了,需要重新登录

二.用户登录日志
  • 参考的博客: SSM实现登录日志
  • 实现思路: 在业务层userServiceImp的loginUser方法后使用 @AfterReturning 后置通知, loginUser我的返回值是User,也就是说,如果有该学生,那么该方法的执行结果是该学生的信息,如果没有该学生,返回值是null,根据是不是null再判断是否要添加这个学生的登录日志,当然你的返回值也可以是int型的,说明该查找操作作用在哪一行,根据是否是-1选择添加登录日志
  • 实现步骤
    • 配置AspectJ开发环境
      • 1.maven依赖

        <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
        </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.2.5.RELEASE</version>
        </dependency>
        
        // 其他....
        // 插件部分
        <build>
        <plugins>
         <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.1</version>
         <configuration>
         <source>1.8</source>
         <target>1.8</target>
         </configuration>
         </plugin>
        </plugins>
        </build>
        
      • 2.基于注解的AOP

        • ① 定义业务接口和实现类,我的业务接口就是userService,其实现类就是userServiceImp,如下

          package com.zhl.service;
          
          import java.util.List;
          
          /**
           * @author ZhangHailong
           * @date 2022/2/23 - 13:45
           * @project_name
           */
          public interface UserService {
          
              // 用户登录
              User loginUser(User user, String ipAddress);
          
          }
          
          
          package com.zhl.service.impl;
          
          import com.zhl.dao.UserDao;
          import com.zhl.entity.User;
          import com.zhl.service.UserService;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;
          
          import java.util.List;
          
          /**
           * @author ZhangHailong
           * @date 2022/2/23 - 13:48
           * @project_name
           */
          
          @Service
          public class UserServiceImpl implements UserService {
          
              @Autowired
              private UserDao userDao;
              
              @Override
              public User loginUser(User user, String ipAddress) {
                  return userDao.findUserByIdAndPwd(user);
              }
          
          
        • ② 定义登录日志实体类

          package com.zhl.entity;
          
          import org.springframework.format.annotation.DateTimeFormat;
          
          import java.util.Date;
          
          /**
           * @author ZhangHailong
           * @date 2022/3/11 - 19:41
           * @project_name 登录日志实体类
           */
          public class LoginLog {
          
              // 用户学号
              private Integer userId;
          
              // 登录时间
              @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
              private Date loginTime;
          
              // ip地址
              private String ipAddress;
          
              public Integer getUserId() {
                  return userId;
              }
          
              public void setUserId(Integer userId) {
                  this.userId = userId;
              }
          
              public Date getLoginTime() {
                  return loginTime;
              }
          
              public void setLoginTime(Date loginTime) {
                  this.loginTime = loginTime;
              }
          
              public String getIpAddress() {
                  return ipAddress;
              }
          
              public void setIpAddress(String ipAddress) {
                  this.ipAddress = ipAddress;
              }
          
              @Override
              public String toString() {
                  return "LoginLog{" +
                          ", userId=" + userId +
                          ", loginTime=" + loginTime +
                          ", ipAddress='" + ipAddress + '\'' +
                          '}';
              }
          }
          
          
        • ③ 定义切面类, 目标对象就是userServiceImp包下的loginUser()

          package com.zhl.aspect;
          
          import com.zhl.dao.LoginLogDao;
          import com.zhl.entity.LoginLog;
          import com.zhl.entity.User;
          import org.aspectj.lang.JoinPoint;
          import org.aspectj.lang.annotation.AfterReturning;
          import org.aspectj.lang.annotation.Aspect;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Component;
          
          import java.util.Date;
          
          /**
           * @author ZhangHailong
           * @date 2022/3/11 - 19:38
           * @project_name
           */
          
          @Aspect
          @Component
          public class LoginLogAspect {
          
              @Autowired
              private LoginLogDao loginLogDao;
          
          
              @AfterReturning(value = "execution(* *..UserServiceImpl.loginUser(..))", returning = "result")
              public void addLoginLog(JoinPoint jp,User result) {
          
                  if (result != null) {
          
                      LoginLog loginLog = new LoginLog();
                      // 登录的id
                      loginLog.setUserId(result.getId());
                      // 登录时间
                      loginLog.setLoginTime(new Date());
                      // 获取loginUser方法的第二个参数,也就是登录的用户的ip,择取需要的填充到LoginLog对象中
                      loginLog.setIpAddress(jp.getArgs()[1].toString());
          
                      loginLogDao.insertLogDao(loginLog);
          
                  }
          
              }		
          }
          
          

          loginUser的第二个参数ipAddress在这里就用到了,AOP是可以通过JoinPoint获取目标方法的参数的,那么在这里拿到,就可以将信息们写入数据库了

        • ④ applicationContext.xml添加

          <!-- 包扫描 -->
          <context:component-scan base-package="com.yy.homework.aspects"/>
          <!-- 配置登陆日志的 AOP 注解-->
          <aop:aspectj-autoproxy/>
          
      • 3.持久层代码

        // Dao接口
        package com.zhl.dao;
        
        import com.zhl.entity.LoginLog;
        
        /**
         * @author ZhangHailong
         * @date 2022/3/11 - 19:48
         * @project_name
         */
        public interface LoginLogDao {
        
            int insertLogDao(LoginLog loginLog);
        
        }
        
        // mapper.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.zhl.dao.LoginLogDao">
        
            <!--select|insert|update|delete语句-->
        
            <insert id="insertLogDao">
              INSERT INTO loginLog(userId,loginTime,ipAddress) values(#{userId},#{loginTime},#{ipAddress})
            </insert>
        
        </mapper>
        

登录的两个功能到这也基本上结束了,谢谢您的观看,新手小白,如果有问题,希望大佬们斧正,也欢迎参与评论

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值