用户登陆退出操作

1. user表设计

字段名称数据类型是否为空备注
idintN用户编号,PK主键
usernamevarchar(80)Y用户名
passwordvarchar(80)Y登录密码 加密之后的密文 加密API
phonevarchar(20)Y手机号
emailvarchar(40)Y邮箱
statustinyintY0-1 布尔类型值 0-false 1-true 启用还是禁用
createddatetimeY创建时间 每张表里需要单独定义 可以进行封装优化
updateddatetimeY修改时间 每张表里需要单独定义 可以进行封装优化

在这里插入图片描述

2. 用户登陆业务实现流程

  • 步骤1: 用户输入完用户名和密码之后,点击登录按钮

  • 步骤2: 准备username/password数据,向后台服务器发送请求,请求类型: post类型

  • 步骤3: 后台服务器接收用户的请求参数 username/password

  • 步骤4: 根据用户名和密码查询数据库
    结果: 有数据 用户名和密码正确 | 没有结果 用户名和密码错误

  • 步骤5: 后端服务器应该返回一个业务回执 标识业务逻辑是否正确执行
    假设: status 200 正确, 201 表示失败

  • 步骤6: 前端服务器根据用户的200/201 提示用户操作成功/操作失败.

3. 用户登录验证接口

说明:一般做前后端交互时,必须有业务接口文档。 文档中详细阐述了 业务需求 / url地址 /参数 / 返回值信息 等要素。

前后端严格按照业务接口文档进行编码。

请求

  • 请求路径: /user/login
  • 请求方式: POST
  • 请求参数
参数名称参数说明备注
username用户名不能为空
password密码不能为空

响应

  • 响应数据 SysResult对象
参数名称参数说明备注
status状态信息200表示服务器请求成功 201表示服务器异常
msg服务器返回的提示信息可以为null
data服务器返回的业务数据返回密钥token信息

返回值格式如下:

{"status":200,"msg":"服务器调用成功!","data":"1e893a97634847b3a8b499b173bea620"}

4.前端

登录界面

路径:src.components.Login.vue

<template>
    <div class="login_container">
      <div class="login_box">
        <!-- 头像区域-->
        <div class="avatar_box">
          <img src="../assets/images/IU.png" alt="VUE图片" />
        </div>

        <!-- 登陆表单区域
              ref代表当前表单引用对象
             :model 是表格中封装的对象
        -->
        <el-form ref="loginFormRef" label-width="0" class="login_form" :model="loginForm" :rules="rules" >
          
          <el-form-item prop="username">
            <el-input  prefix-icon="iconfont iconuser" v-model="loginForm.username"></el-input>
          </el-form-item>
          
          <el-form-item prop="password">
            <el-input  prefix-icon="iconfont iconsuo" type="password" v-model="loginForm.password"></el-input>
          </el-form-item>
          
          <el-form-item class="btns">
             <el-button type="primary" @click="login">登录</el-button>
              <el-button type="info" @click="resetBtn">重置</el-button>
          </el-form-item>
        
        </el-form>
      </div>
    </div>
</template>

在这里插入图片描述

编辑login登录实现方法

路径:src.components.Login.vue

login(){
  //获取表单对象之后进行数据校验
  //valid 表示校验的结果 true表示通过  false表示失败
  this.$refs.loginFormRef.validate(async valid => {
     //如果没有完成校验则直接返回
     if(!valid) return
     //对输入框的数据进行封装,如果校验成功,则发起ajax请求 使用post类型
    const {data: result} = await this.$http.post('/user/login',this.loginForm)
    if(result.status !== 200) return this.$message.error("用户登录失败")
    //登录信息响应提示框
    this.$message.success("用户登陆成功")
    //获取用户token信息
    let token = result.data 
    //使用session的方式临时保存用户token信息
    window.sessionStorage.setItem("token",token)
    //用户登录成功之后,跳转到home页面
    this.$router.push("/home")
  })
}

编辑路由规则(页面跳转必配)

路径:src.router.index.vue

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../components/Login.vue'
import Home from '../components/Home.vue'

//使用路由机制 通过 children 实现路由嵌套, 通过 redirect 实现重定向
Vue.use(VueRouter)
const routes = [
  {path: '/', redirect: '/login'},
  {path: '/login', component: Login},
  {path:'/home',component:Home}
]

//配置路由对象 先定义后使用
const router = new VueRouter({
  //vue对象挂载路由 router: router
  routes
})
token的作用

说明: 前端服务器: 用户进行登陆操作时 输入用户名和密码进行校验!!!
将数据信息发送到后端服务器进行校验,查询数据库。

假设: 用户用户名和密码正确!!! 页面应该跳转到系统的首页 “/home”
问题: 是否可以在浏览器中直接输入 “/home” 理论上不允许访问该页面!

解决方案:
后端服务器返回一个独一无二的 token数据, 前端只要携带token 认为该用户已经登陆。可以跳转页面.。权限操作雏形!!!
总结: token是用来标识用户已经登陆!!!

Session

Session: 在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。 Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。有关使用Session 对象的详细信息,请参阅“ASP应用程序”部分的“管理会话”。注意会话状态仅在支持cookie的浏览器中保留。

总结:

  1. Session 是会话控制
  2. Session可以用户存储数据
  3. Session生命周期整个会话 在会话期间数据有效, 如果会话窗口关闭则数据清除
  4. Session数据存储在浏览器的内存中(前端的)
Cookie(了解)

Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 。

总结:

  1. Cookie 是一个文本文件
  2. Cookie 存储的是用户信息 (加密数据 更加安全)
  3. Cookie 保存到用户的计算机终端中 可以临时/永久的存储信息.

关于Session和Cookie的例子
手机银行的用户登录信息? session 安全性要求较高
购物网站 要求用户七天免密登录? 使用Cookie进行存储!!
公司的财务系统的登录信息? 建议使用Session
电影: 没有绝对安全的系统

总结: 如果对于数据安全性要求较高,则使用Session。 如果存储一些大量查询的数据(不重要的)一般采用Cookie进行保存。

路由守卫语法

路径:src.router.index.vue

业务说明
当用户没有登录时,不可以访问其他页面,如果sessionStorage中没有token数据,则表示没有登录。用该拦截,跳转到登录页面。

/* 配置路由导航守卫
 当用户没有登录时,不可以访问其他页面 如果sessionStorage中没有token数据,则表示没有登录 用该拦截,跳转到登录页面
 关于参数说明:
   1. to 将要访问的路径
   2. from 从哪个路径跳转来的
   3. next 是一个函数   next() 表示放行  next("/login") 强制跳转*/

//router.beforeEach(function(parameter2,parameter2,parameter3){})
router.beforeEach((to,from,next) => {
    //1.当用户访问登录页面,则直接放行 如果不需要执行后续操作 执行return(返回结果并终止程序)
    if(to.path === '/login') return next()
    //2.当用户访问其他页面 需要校验是否有token
    let token = window.sessionStorage.getItem('token')
    //如果数据为null  则访问登录页面
    if(!token)  return next('/login')
    //如果数据不为null 则放行
    next()
})

用户退出操作

业务说明
当用户点击退出按钮时,应该删除sessionStorage中的token信息. 并且访问登录页面

路径:src.components.Home.vue

logout() {
        //1.删除session中的数据
        window.sessionStorage.clear()
        //2.用户访问登录页面
        this.$router.push('/login')
      }

5. 后端

创建BasePojo类

创建包: com.jt.pojo
创建类: BasePojo .java

//pojo基类,完成2个任务,2个日期,实现序列化
@Data
@Accessors(chain=true)
public class BasePojo implements Serializable{
	@TableField(fill = FieldFill.INSERT)
	private Date created;	//表示入库时需要赋值
	@TableField(fill = FieldFill.INSERT_UPDATE)
	private Date updated;	//表示入库/更新时赋值.
}

创建User类

创建包: com.jt.pojo
创建类: User.java

@Data //动态生成get/set方法
@TableName("user") //对象与表一一对应
@Accessors(chain = true) //链式加载结构
public class User extends BasePojo{
    @TableId(type = IdType.AUTO)//ID主键自增
    private Integer id;
    private String username;
    private String password;
    private String phone;
    private String email;
    private Boolean status;
    @TableField(exist = false)  //该属性在表中不存在
    private Role role;  //定义role角色数据
}

创建SysResult类(系统返回值)

关于SysResult对象的说明: 该对象用来实现后端与前端业务的交互
业务执行正确 status=200 业务执行错误 status=201
概念: 前后端交互的层级 定义为 VO层
在这里插入图片描述

创建包: com.jt.vo
创建类: SysResult .java

//作用: 实现前后端交互
@Data
@Accessors(chain = true)
@NoArgsConstructor  //无参构造
@AllArgsConstructor //全参构造
public class SysResult implements Serializable { //规范的写法
    private Integer status;  //状态码  200 201
    private String msg;      //服务器返回的提示信息
    private Object data;     //服务器返回的业务数据

    //重载:  方法名称相同,参数不同
    //为了用户使用VO对象 更加的方便 重载一些方法 简化程序的调用
    public static SysResult fail(){
        return new SysResult(201, "业务执行失败",null);
    }
    
    //1.不带参数的正确返回
    public static SysResult success(){
        return new SysResult(200, "服务器处理成功", null);
    }

    //2.带返回值的正确返回  用户传递什么/返回值就是什么
    public static SysResult success(Object data){
        return new SysResult(200, "服务器处理成功", data);
    }

    //3.带返回值,携带提示信息
    public static SysResult success(String msg,Object data){
        return new SysResult(200, msg,data);
    }

}

编辑UserController类

所属包: com.jt.controller

业务要求: 完成用户信息校验,并且返回特定的token数据

 /**
     * 业务需求:用户登陆校验
     * 类型:POST
     * URL: /user/login
     * 参数: username/password json串 {username: "xxx", password: "xxx"}
     * 返回值: SysResult对象  data的String类型的信息 token
     * 用户名/密码 admin123/admin123456
     */
    @PostMapping("/login")
    public SysResult login(@RequestBody User user){
        //1.根据用户名和密码校验 返回token Service层中完成
        String token = userService.login(user);
        //2. token 有值业务正确   | null 业务操作失败
        if(token == null){
            return SysResult.fail();
        }
        return SysResult.success(token);
    }

编辑UserServiceImpl实现类

所属包: com.jt.sercvice

/**
     * 需求:
     *      1.根据用户名和密码查询数据库
     *      2.将密码进行加密处理 md5加密方式
     *      3.如果用户名和密码正确 返回token
     *      4 UUID: 每次生成的UUID几乎不重复.   重复概率 2^128/1
     *        b809cd3e-f4fa-11eb-b396-52152e05da50
     * @param user  作用: 在未来生成API文档时 有效果 一般都是默认的
     * @return
     */
    @Override
    public String login(User user) {
        //1.将密码进行加密的处理
        String password = user.getPassword(); //明文
        //2. 将字符串 转化为字节数组
        byte[] passByte = password.getBytes();
        //将明文加密
        String md5Pass = DigestUtils.md5DigestAsHex(passByte);
        //3. 根据用户名和密文查询数据库
        //Sql: select * from user where uname="xxx" and ps="xx"
        //根据对象中不为null的属性充当where条件!!!!
        user.setPassword(md5Pass);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
        //从数据库中获取结果
        User userDB = userMapper.selectOne(queryWrapper);
        
        if(userDB == null){ //用户名和密码错误 返回null
            return null;    //业务流程结束
        }
        
        //如果程序执行到这一行,则数据用户的输入正确的. 返回token
        String token = UUID.randomUUID().toString().replace("-","");
        return token;
    }

MD5介绍

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

总结:
1.MD5信息摘要算法
2.通常可以将数据进行MD5加密 生成 “数字指纹”
3.现阶段md5的加密的算法应用于各大网站中
4.md5加密之后 理论上来说 无法由密文转化为明文 不可以反向编译
5. 限定输入密码的次数!!! 3-5次 锁定账户!!!

核心算法:
知识回顾: 高中的函数!!!
什么是函数: 给定未知数x 经过函数计算 得到一个唯一的结果y
实质: MD5的本质就是hash算法!!!
在这里插入图片描述
流传的MD5可以被破解的原理: 就是将md5进行反向查询

在这里插入图片描述

md5 改进版: hash(明文+ 盐值) 了解即可

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐