欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

登陆注册流程和token加密

程序员文章站 2022-04-18 17:21:40
...

有问题的知识点

  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


相关标签: Node vue