登陆注册流程和token加密

vue 同时被 2 个专栏收录
6 篇文章 0 订阅
2 篇文章 0 订阅

有问题的知识点

  1.    // [ result.status == 1 && 'token' ]: result.status == 1 && token 
       token: result.status == 1 && token || '用户名密码错误,token不返回'
    
  2. 操作数据库 mongoose

一.token 重点

  1. 什么是token?

    • token是一段经过后端处理【 后端加密算法 】的特殊字符,后端在前端登录时,会给前端返回这个字符,前端拿到这个字符之后,要将它存入cookie,
  2. token的作用是什么?

    • 项目自动登录
    • 身份验证
      • 前端发送的每一个数据请求,要求携带一个token数据
    • 权限验证
      • 普通用户
      • 会员用户
      • 管理员
      • 原理:
        • 当用户注册并登录后,后端会给它返回一个token字符,
  3. 使用

    • 软件安装教程
    • 根目录创建了一个rsa文件夹: 用于存放公钥和私钥
      • 私钥 -> 加密
      • 公钥 -> 解密
  4. 生成token要用

    • 安装 openssl 软件(后端软件)
    • 引入第三方模块 jsonwebtoken (npm i jsonwebtoken -S ),使用方式见npm官网
    • 通过软件,在终端里面输入以下命令,能生成 非对称加密 通过私钥产生token 通过公钥解密token
    // 1.产生公钥和私钥
    // 产生私钥  openssl genrsa -out ./private_key.pem 1024    1024 代表私钥长度
    // 产生公钥  openssl rsa -in ./private_key.pem -pubout -out ./public_key.pem
    

二.登陆注册流程

  1. 创建项目

npm express -generator -g
npx express -e . (-e 表示项目使用ejs 模板, . 表示在当前目录创建项目)
该命令在npm 是5.2以上版本会 省略安装 npm express -generator -g

  1. 前端发ajax 请求,并判断cookie 有没有token,有cookie token存在自动登陆。否则要生成token字符

  // 自动登录

  function load () {
    const token = cookieUtil.get('TOKEN')
    if ( token  ) {
      setTimeout(function () {
        location.href = "./index.html"
      },2000)
    }
  }
  //发请求,少些内容了
   $.ajax({
    url: 'http://localhost:3000/login',
    data: {
        username: $('#username').val(),
        password: $('#password').val(),
        token: cookieUtil.get( 'TOKEN' )
      },
   })
  1. epxress 脚手架 响应数据和打造接口

router.route(’/login’).post(( req,res,next )=>{} ) 这是配置路由的一种链式写法
router.post(’/login’,( req,res,next )=>{} ) 这是配置路由的另一种写法
req.body 是前端发送请求发送来的内容
res.render(‘login’,{ data: {})===== login第一个参数是渲染模板名字,第二个参数是发给前端的值

const router = express.Router()
router.route('/login')//配置路由
.post( async ( req,res,next )=>{})
// 进行数据库操作
const result = await users.query( req.body )

  res.render('login',{//login 是渲染的模板ejs的名字,后缀名可省略
        data: JSON.stringify({//data是返回给前端的内容
          status: result.status,
          info: result.info,
          token: result.status == 1 && token || '用户名密码错误,token不返回'
        })
  })
  1. 解决跨域

npm i cor -S 在pp根组件

var cors = require('cors')
// 在使用中间件前面解决跨域
app.use(cors({
  "origin": "*",
  "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
  "preflightContinue": false,
  "optionsSuccessStatus": 200
}))
  1. 数据库操作
  * 什么是mongoose?
    * 它就是一个用于操作MongoDB数据库的一个对象,是一个封装对象
  * mongoose使用?
    *  1. 引入mongoose
    *  2. 连接数据库
    *  3. 创建骨架【 定义字段 】   
    *  4. 创建模型 -> 用于操作数据库 
    *  5. 创建实体 -> 用于数据库增加操作

  1. token 生成和 路由文件配置路由

(token 是后端文件,所以前端html文件要放到服务器下)
打造接口,app.use(’/’,loginRouter) 使用中间件,在根目录使用,相当于和二级路由路径拼接
安装npm 第三方插件 jsonwebtoken
const private_key = fs.readFileSync( path.join( __dirname, ‘…/rsa/private_key.pem’))
username 是准备要加密的内容,通过jsonwebtoken来生成token字符
const token = jwt.sign( username,private_key,{ algorithm: ‘RS256’ } )

const { users } = require('../database')

// 打造login接口
const jwt = require('jsonwebtoken') 
router.route('/login') // 打造了  http://localhost:3000/login
  .post( async ( req,res,next ) => {
    // 接收前端发来的数据 console.log('req.body',req.body) 
    // 如果前端的token是空的,那么我们需要返回给它新的token
    // 如果有,那么自动登录
    const { token,username } = req.body 

    if ( !token ) {
      // 表示token是空的,我们要返回新的给它
      // 生成token给它

      // 1. 通过fs来读取私钥
      const private_key = fs.readFileSync( path.join( __dirname, '../rsa/private_key.pem'))
      // 2. 通过jsonwebtoken来生成token字符

      // jwt.sign( 数据, 私钥, 加密算法配置 )
      //username 是准备要加密的内容
      const token = jwt.sign( username,private_key,{ algorithm: 'RS256' } )

      // 进行数据库操作
      const result = await users.query( req.body )
      res.render('login',{
        data: JSON.stringify({
          status: result.status,
          info: result.info,
          // [ result.status == 1 && 'token' ]: result.status == 1 && token 
          token: result.status == 1 && token || '用户名密码错误,token不返回'
        })
      })

    }

  })

module.exports = router  // 导出模块

三 .mongoose来操作MongoDB

mongoose使用?
* 1. 引入mongoose
* 3. 创建骨架【 定义字段 】
* 4. 创建模型 -> 用于操作数据库
* 5. 创建实体 -> 用于数据库增加操作

说明:

  • 只有add(req.body)增加的时候采用实体 ,把请求的内容当参数传过来
  • userModel.find({},( err,docs ) 查找数据库的所有,
  • docs 就是数据库查到的结果,是一个数组 [{}]
  • 存数据
  • const userEnity = new userModel( req.body )
  • userEnity.save( err => {})
// *  1. 引入mongoose
  const mongoose = require('mongoose') // mongoose 就是一个实例,这个实例身上有很多的方法

//    2. 连接数据库

 const DB_URL = `mongodb://${ HOST }:27017/${ DB_NAME }`    //DB_NAME数据库名字
 mongoose.connect( DB_URL, err => { // 错误优先的回调函数
    // ! 错误优先指的是第一个参数是err/error
    if ( err ) {
      console.log( err )
    } else {
      // 连接成功
      console.log('数据库连接成功')
    }
  })

//3. 创建骨架 Schema 【 定义字段 】    类似: 一个表就是一个骨架,所以骨架不止一个

       const userSchema= new mongoose.Schema({
        username: String,
        password: String
        })

//4. 创建模型 -> 用于操作数据库 
    // const useModel = mongoose.model( 集合名称【 复数 】,对应的骨架 
    const userModel = mongoose('users',userSchema)//users 是数据库集合的名字

//5. 创建实体,是增加的时候才创建  const userEnity = new userModel( data )  , userEnity.save(),存数据库

// * 6. 数据库操作  CURD
// 是对users集合的操作,操作的是userModel模型

  // 增加   userModel.save()

  // 删除   userModel.findById( _id, ( err,doc ) => { doc.remove() })

  // 修改   userModel.findById( _id, ( err,doc ) => {  doc.username = xxx   doc.save() })

  // 查询   user.find({},( err,docs ) => {  })

四 .token的补充说明

JWT【 全称: JsonWebToken 】

  • 用户登录 服务器端产生一个token (加密字符串) 发送给前端

  • 前端将token 进行保存

  • 前端发起数据请求的时候携带token

  • 服务端 验证token 是否合法 如果合法继续操作 不合法终止操作

  • token 的使用场景 无状态请求 保持用户的登录状态 第三方登录(token+auth2.0)

非对称加密 通过私钥产生token 通过公钥解密token

// 1.产生公钥和私钥
// 产生私钥  openssl genrsa -out ./private_key.pem 1024    1024 代表私钥长度
// 产生公钥  openssl rsa -in ./private_key.pem -pubout -out ./public_key.pem

 let private_key=fs.readFileSync(path.join(__dirname,'./private_key.pem'))
 let public_key=fs.readFileSync(path.join(__dirname,'./public_key.pem'))
 var token = jwt.sign(palyload, private_key,{ algorithm: 'RS256'});
 console.log(token)
 let  token='eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IueUqOaIt2lkIiwiaWF0IjoxNTUxMTUyNzk1fQ.TI_xDBvObHGAH7EV40WWpQemm5nx077Gdjq-pzDx0NWN5YFd40S7XcLmgoDdYscLM7vMOP0c7z1l83JUixqk7IBjBCU-tMNo_G5_-LGkQjV3vDYq_3TkXTl42lgmFA-EBey7W6W1PgPfYlowyHAyp-07hXaMRevgVkXm2lPEFXo'

  var decoded = jwt.verify(token, public_key);

五. 数据库的增删改查

    /* 
  * 此文件是对users集合的操作
*/
const { userSchema } = require('../schema')
const model = require('../model')
const userModel = model('users',userSchema)
const users = {
  add ( data ) {
    // 我现在要将add方法的处理结果返到add函数外面
    return new Promise(( resolved,rejected ) => {
      // 得到实体 
      // 判断用户名是否已经存在
  
      userModel.find({},( err,docs ) => {
      // console.log("西阁: add -> docs", docs)
        // docs 就是数据库查到的结果    [{}]
        const f = docs.some( item => data.username == item.username )
        if ( f ) {
          // 如果是true,那么数据库是有这个用户名
          resolved({
            status: 2,
            info: '用户名已经重复'
          })
        } else {
          // 数据库没有这个用户名
          // 存数据
            const userEnity = new userModel( data ) 
            userEnity.save( err => {
              if ( err ) {
                rejected({
                  status: 0,
                  info: '注册失败'
                })
              } else {
                resolved({
                  status: 1,
                  info: '注册成功'
                })
              }
            })
        }
      })
    })

  
  },
  del () {},
  update ( data ) {
    return new Promise(( resolved,rejected ) => {
       // data  username   新的密码  password 
       userModel.find({ username: data.username }, ( err,docs ) => {
        //  console.log('docs',docs) // []  / [{}]
         if ( docs.length != 0 ) {
            userModel.findById( docs[0]._id, ( err, doc ) =>  {
              // console.log("西阁: update -> doc", doc)
              doc.password = data.password
              doc.save( err => {
                if ( err ) {
                  rejected({
                    status: 0,
                    info: '修改失败'
                  })
                } else {
                  resolved({
                    status: 1,
                    info: '修改成功'
                  })
                }
              })
            })
         } else {
           // 用户名不存在的
           resolved({
            status: 2,
            info: '用户名不存在'
           })
         }

       })
    })
  },
  query ( data ) {
    // data是前端发过来的数据 
    return new Promise(( resolved,rejected ) => {
      userModel.find({},( err,docs ) => {
        // docs就是查询的结果  [{},{}]
        const f = docs.some( item => (item.username == data.username && item.password == data.password) )
        if ( f ) {
          // f -> true  用户名、密码是正确的
          resolved({
            status: 1,
            info: '登录成功'
          })
        } else {
          // f -> false  用户名或者密码错误了
            resolved({
            status: 2,
            info: '用户名或是密码错误'
          })
        }
      })
    })
  }
}

module.exports = users


  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值