需求介绍—开发登录,退出功能

访问登录页面:点击头部区域的链接打开登录页面

登录:

  • 验证账号,密码,验证码
  • 成功时生成登录凭证发放给客户端,失败时跳转回登录页面

退出:

  • 将登录状态修改为失效的状态
  • 跳转至往网站的首页

代码实现

现在我们暂时把登录凭证存到数据库里面有一张表login_tickrt,以后会存到Redis里面。

那么首先要把登录凭证的相关操作实现了,首先写个实体类对应login_tickrt表里的数据,将其封装起来

package com.nowcoder.community.entity;

import java.util.Date;

public class LoginTicket {
private int id;
private int userId;
private String ticket;
private int status;
private Date expired; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public int getUserId() {
return userId;
} public void setUserId(int userId) {
this.userId = userId;
} public String getTicket() {
return ticket;
} public void setTicket(String ticket) {
this.ticket = ticket;
} public int getStatus() {
return status;
} public void setStatus(int status) {
this.status = status;
} public Date getExpired() {
return expired;
} public void setExpired(Date expired) {
this.expired = expired;
} @Override
public String toString() {
return "LoginTicket{" +
"id=" + id +
", userId=" + userId +
", ticket='" + ticket + '\'' +
", status=" + status +
", expired=" + expired +
'}';
}
}

  

接下来实现数据访问的逻辑,那么新建一个接口LoginTicketMapper,对应的有以下几种方法:增加一个凭证,依据ticket来查凭证,修改凭证的状态。

这次我们通过注解的方式实现sql查询。

package com.nowcoder.community.dao;

import com.nowcoder.community.entity.LoginTicket;
import org.apache.ibatis.annotations.*; @Mapper
public interface LoginTicketMapper { @Insert({
"insert into login_ticket(user_id,ticket,status,expired) ",
"value(#{userId},#{ticket},#{status},#{expired})"
})
// 希望id自动生成,
@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(String ticket, int status);
}

  

那么现在就开发业务层UserService

// 封装一个Map,返回多种情况的返回结果
public Map<String, Object> login(String username, String password, long expiredSeconds) {
Map<String, Object> map = new HashMap<>();
if(StringUtils.isBlank(username)) {
map.put("usernameMsg", "账号不能为空");
}
if(StringUtils.isBlank(password)) {
map.put("passwordMsg", "密码不能为空");
} // 验证账号
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 (!user.getPassword().equals(password)) {
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 * 1000));
loginTicketMapper.insertLoginTicket(loginTicket); map.put("ticket", loginTicket.getTicket());
return map;
}

  

那么现在写表现层,写LoginController来处理页面传来的请求,写能处理请求的方法就可以了。

对于记住我的勾选我们要有不同的保存时间,所以我们定义两个常量的时间比较好,在CommunityConstant里添加定义:

/**
* 默认状态的登录凭证的超时时间
*/
int DEFAULT_EXPIRED_SECONDS = 3600 * 12; /**
* 记住状态的登录凭证的超时时间
*/
int REMEMBER_EXPIRED_SECONDS = 3600 * 24 *100;

  

辅助功能完成就写对应的表现层:

// 我们在决定Cookie的有效路径,最好是用变量来显示比较方便
@Value("${server.servlet.context-path}")
private String contextPath; @RequestMapping(path = "/login", method = RequestMethod.POST)
public String login(String username, String password, String code, boolean rememberme, Model model, HttpSession httpSession, HttpServletResponse httpServletResponse) {
// 检查验证码
String kaptcha = (String) httpSession.getAttribute("kaptcha"); if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) {
model.addAttribute("codeMsg","验证码不正确");
return "/site/login";
} // 检查账号,密码
int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;
Map<String, Object> map = userService.login(username, password, expiredSeconds);
if(map.containsKey("ticket")) {
// 需要给客户端发送一个Cookie
Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
cookie.setPath(contextPath);
cookie.setMaxAge(expiredSeconds);
httpServletResponse.addCookie(cookie);
return "redirect:/index";
}
else {
model.addAttribute("usernameMsg", map.get("usernameMsg"));
model.addAttribute("passwordMsg", map.get("passwordMsg"));
return "/site/login";
}
}

  

最后开发退出:

首先数据层我们已经写好了,只需要写个业务层和表现层

// 业务层调一下mapper的update方法就可以了
public void logout(String ticket) {
loginTicketMapper.updateStatus(ticket, 1);
}

  

表现层要从Cookie中拿到ticket,然后调业务层。

@RequestMapping(path = "/logout", method = RequestMethod.GET)
public String logout(@CookieValue("ticket") String ticket) {
userService.logout(ticket);
return "redirect:/login";
}

  

SpringBoot开发十-开发登录,退出功能的更多相关文章

  1. Atitit.用户权限服务 登录退出功能

    Atitit.用户权限服务 登录退出功能 参数说明 /com.attilax/user/loginOut.jsp?url="+url Utype=mer 作者::  ★(attilax)&g ...

  2. [转] 从零构建 vue2 + vue-router + vuex 开发环境到入门,实现基本的登录退出功能

    这是一个创建于 738 天前的主题,其中的信息可能已经有所发展或是发生改变. 前言 vue2 正式版已经发布将近一个月了, 国庆过后就用在了公司的两个正式项目上, 还有一个项目下个月也会采用 vue2 ...

  3. Struts2 + Hibernate3.3 开发简单的登录注册功能【J2EE】

    开发环境: IDE:Myeclipse10.0 数据库:Oracle(SQL Developer) Web容器:Tomcat 7.0 JDK:1.6 Struts:2.0 Hibernate:3.3 ...

  4. SpringBoot Web开发(5) 开发页面国际化+登录拦截

    SpringBoot Web开发(5) 开发页面国际化+登录拦截 一.页面国际化 页面国际化目的:根据浏览器语言设置的信息对页面信息进行切换,或者用户点击链接自行对页面语言信息进行切换. **效果演示 ...

  5. Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能

    Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...

  6. flask 开发用户登录注册功能

    flask 开发用户登录注册功能 flask开发过程议案需要四个模块:html页面模板.form表单.db数据库操作.app视图函数 1.主程序 # app.py # Auther: hhh5460 ...

  7. SpringBoot整合MyBatis-Plus实现快速业务功能开发

    概览:使用MybatisPlus和它的代码生成整合SpringBoot可以实现快速的业务功能开发,具体步骤如下 一.添加依赖 <dependency> <groupId>org ...

  8. SpringBoot:Web开发

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 , 基于atguigu 1.5.x 视频优化 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处 ...

  9. 第十三章 Odoo 12开发之创建网站前端功能

    Odoo 起初是一个后台系统,但很快就有了前端界面的需求.早期基于后台界面的门户界面不够灵活并且对移动端不友好.为解决这一问题,Odoo 引入了新的网站功能,为系统添加了 CMS(Content Ma ...

随机推荐

  1. 资源:zookeeper下载地址

    提供zookeeper下载地址:https://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/

  2. logback学习与配置使用

    Logback介绍 Logback 分为三个模块:Core.Classic 和 Access.Core模块是其他两个模块的基础. Classic模块扩展了core模块. Classic模块相当于log ...

  3. Windows软件包管理工具:Scoop

    前言 删库跑路后,Windows系统如何快速安装应用程序,部署环境呢? 以前想过这个问题,最近在安装Hugo时发现使用软件包管理工具可以解决这个问题. 阅读建议 首先需要测试下载速度,尝试从官网下载, ...

  4. 递推算法,AI衍生

    引言 最近在刷leetcode算法题的时候,51题很有意思: 题目是这样的: n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击.给你一个整数 n ,返回 ...

  5. 你真的了解 Session 和 Cookie 吗?

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 前言 ...

  6. DL基础补全计划(三)---模型选择、欠拟合、过拟合

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  7. Linux系统引导过程及排除启动故障

    一.Linux操作系统引导过程二.系统初始化进程1.init进程2.Systemd3.Systemd单元类型三.排除启动类故障[1].修复MBR扇区故障(含实验过程)[2].修复GRUB引导故障●方法 ...

  8. 一文搞懂一致性hash的原理和实现

    在 go-zero 的分布式缓存系统分享里,Kevin 重点讲到过一致性hash的原理和分布式缓存中的实践.本文来详细讲讲一致性hash的原理和在 go-zero 中的实现. 以存储为例,在整个微服务 ...

  9. python 得到汉字的拼音

    import pypinyin # 不带声调的(style=pypinyin.NORMAL) def pinyin(word): s = '' for i in pypinyin.pinyin(wor ...

  10. [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator

    [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (18) --- kube ...