写在前面:
登录涉及到存放用户信息,应该选择session还是cookie?

1.实体类(LoginTicket)用数据库保存登录状态

@Data
public class LoginTicket {
    private int id;
    private int userId;
    private String ticket;
    private int status;
    private Date expired;
}

2.Mapper层

@Mapper
public interface LoginTicketMapper {

    //插入状态
    @Insert({
            "insert into login_ticket(user_id,ticket,status,expired)",
            "value(#{userId},#{ticket},#{status},#{expired})"
    })
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertLoginTicket(LoginTicket loginTicket);

    //查询状态
    @Select({
            "select id,user_id,ticket,status,expired",
            "from login_ticket",
            "where ticket = #{ticket}"
    })
    LoginTicket selectByTicket(String ticket);

    //更新状态
    @Update({
            "update login_ticket",
            "set status = #{status}",
            "where ticket = #{ticket}"
    })
    int updateStatus(@Param("ticket") String ticket, @Param("status") int status);
}		

3.实现登录逻辑(Service层)

public Map<String, Object> login(String username, String password, int expiredSeconds) {
    Map<String, Object> map = new HashMap<>();
    //空值处理
    if (StringUtils.isBlank(username)) {
        map.put("usernameMsg", "用户名不得为空!");
        return map;
    }
    if (StringUtils.isBlank(password)) {
        map.put("passwordMsg", "密码不得为空!");
        return map;
    }
    //验证账号
    User user = userMapper.selectByName(username);
    if (user == null) {
        map.put("usernameMsg", "该用户不存在!");
        return map;
    }
    //验证账号状态
    if (user.getStatus() == 0) {
        map.put("usernameMsg", "该用户尚未激活,请前往邮箱查看并激活!");
        return map;
    }
    //验证密码
    password = CommunityUtil.md5(password + user.getSalt());
    if (!password.equals(user.getPassword())) {
        map.put("passwordMsg", "用户密码错误");
        return map;
    }
    //生成登录凭证
    LoginTicket loginTicket = new LoginTicket();
    loginTicket.setUserId(user.getId());
    loginTicket.setTicket(CommunityUtil.generateUUID());
    loginTicket.setStatus(0);
    loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000L));
    loginTicketMapper.insertLoginTicket(loginTicket);
    map.put("ticket", loginTicket.getTicket());
    return map;
}

ps:loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000L));
此处要将Integer转化为Long,存储单位为秒,Integer长度显然不足

expiredSeconds参数用来接收用户选择此次登录时长以及cookie存在时长,如:
在这里插入图片描述
并设置常数接口;

/**
 * 默认登录凭证超时时间
 */
int EXPIRED_SECOND_DEFAULT = 60 * 60 * 12;
/**
 * 记住状态登录凭证超时时间
 */
int EXPIRED_SECOND_REMEMBER = 60 * 60 * 24 * 100;

4.与前端交互(Controller)

@PostMapping("/login")
public String login(String username, String password, String code, Model model, HttpSession session, boolean rememberMe, HttpServletResponse respones) {
    //验证码为空
    if (code == null || StringUtils.isBlank(code)) {
        model.addAttribute("codeMsg", "请填写验证码!");
        return "/site/login";
    }
    //验证码错误
    String kaptcha = (String) session.getAttribute("kaptcha");
    if (StringUtils.isBlank(kaptcha) || !kaptcha.equalsIgnoreCase(code)) {
        model.addAttribute("codeMsg", "验证码填写错误!");
        return "/site/login";
    }
    //检查账号密码
    int expiredSecond = rememberMe ? EXPIRED_SECOND_REMEMBER : EXPIRED_SECOND_DEFAULT;
    Map<String, Object> map = userService.login(username, password, expiredSecond);
    if (map.containsKey("ticket")) {
        Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
        //获得该cookie的范围
        cookie.setPath(contextPath);
        cookie.setMaxAge(expiredSecond);
        respones.addCookie(cookie);
        return "redirect:/index";
    } else {
        model.addAttribute("usernameMsg", map.get("usernameMsg"));
        model.addAttribute("passwordMsg", map.get("passwordMsg"));
        return "/site/login";
    }
}

账号密码交由服务层判断,验证码信息在controller层判断即可(如何使用springboot实现验证码?)

thymeleaf模板保存数据(防止登录错误信息需要全部重新输入)使用:thymeleaf会自动从当前model中查询该字段

在这里插入图片描述

查看是否登录

  • 网页浏览cookie信息(F12→Application→Cookie)
  • 数据库查看

5.退出功能实现

//service层
@Override
public void logout(String ticket) {
    loginTicketMapper.updateStatus(ticket,1);
}
//controller层
@GetMapping("/logout")
public String logout (@CookieValue("ticket") String ticket){
    userService.logout(ticket);
    return "redirect:/login";
}

通过查看数据库确认是否该次登陆已退出

点击看gitee源码!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐