栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

1.登录模块

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

1.登录模块

登录模块主要实现的功能有: ① 登录功能: 用户输入学号,密码,验证码验证登录 ② 用户登录日志: 用户登录成功后,将用户的学号,登录时间,ip地址存入数据库 一. 登录功能

验证码模块实现的思想: 后台将生成验证码传给前端,并同时保存到session中, 用户输入学号,密码,验证码发送给后端, 后端取出session中的验证码进行对比,如果验证码错误,直接返回字符串"验证码错误", 如果验证码正确,继续查找是否存在该用户,如果存在, 返回"用户存在", 不存在返回 “用户不存在”

验证码实现: 我是整合了Kaptcha,实现了验证码的功能, 大佬博客: 1.这篇是整合kaptcha步骤,基本上是照着做的 , 2.这篇我参考了这篇的验证码校验部分,将其添加到自己的登录验证代码中

遇到的问题: 我做这块的时候,当用户进入登录页面的时候,后台不是向前端发送验证码然后将这个验证码存到session中么,但是当我携带学号,密码,和验证码发送到后台时,第一次存的验证码竟然是null了,看了一篇博客试了试,哎,您猜怎么着,解决了, 大佬博客: 解决axios跨域请求两次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;


@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("验证码错误", "提示", {
            /confirm/iButtonText: "确认",
          });
          this.$refs.codeClickPosition.focus();
          this.loginForm.code = "";

        }
        else {
          
          this.loading = false;
          this.$alert("用户名或密码错误!", "提示", {
            /confirm/iButtonText: "确认",
          });
          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依赖


junit
junit
4.11
test


org.springframework
spring-context
5.2.5.RELEASE


org.springframework
spring-aspects
5.2.5.RELEASE


// 其他....
// 插件部分


 
 maven-compiler-plugin
 3.1
 
 1.8
 1.8
 
 


2.基于注解的AOP

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

package com.zhl.service;

import java.util.List;


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;



@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;


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;



@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添加





3.持久层代码

// Dao接口
package com.zhl.dao;

import com.zhl.entity.LoginLog;


public interface LoginLogDao {

    int insertLogDao(LoginLog loginLog);

}
// mapper.xml





    

    
      INSERT INTO loginLog(userId,loginTime,ipAddress) values(#{userId},#{loginTime},#{ipAddress})
    


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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/763209.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号