zoukankan      html  css  js  c++  java
  • 一个关于vue+mysql+express的全栈项目(三)------ 登录注册功能的实现(已经密码安全的设计)

    本系列文章,主要是一个前端的视角来实现一些后端的功能,所以不会讲太多的前端东西,主要是分享做这个项目学到的一些东西,,,,,

    好了闲话不多说,我们开始搭建后端服务,这里我们采用node的express框架来做我们的后端服务

    这里是官网地址:express

    一、安装express框架

    npm install express --save

    二、先写一个测试的接口

    在根目录下新建一个server的文件夹,并新建一个server.js

     1 const express = require('express')
     2 
     3 const app = express()
     4 
     5 const Router = express.Router()
     6 
     7 Router.get('/test', function(req, res) {
     8   return res.json({
     9     code: 0,
    10     data: 'hello world!'
    11   })
    12 })
    13 
    14 app.use('/testRouter', Router)
    15 
    16 app.listen(3001, function() {
    17   console.log('express server is success')
    18 });

    接下来我们在node环境中运行server.js

    打开浏览器,输入localhost://3001/testRouter/test;可以看到以下结果

    接下来就是安装mysql,具体安装参照百度

    三,使用node做为服务端,来操作数据库的话,我们最好选用一个orm,这样可以方便我们更好的操作数据库,想基于MongoDB有mongoose;mysql有sequelize

      这里因为我们的数据库选用的是mysql,那么我们就选择sequelize,首先安装sequelize

    npm install sequelize --save
    npm install mysql2 --save

    然后打开我们的数据库命令窗口mysql,输入密码,默认密码为root

    创建一个数据库

    CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET [=] charset_name
    {}表示参数必选 | 表示选择一个
    []表示参数可选
    {DATABASE | SCHEMA}任选其一
    [IF NOT EXISTS] 可以忽略创建重复数据库是,系统的报错信息(从而产生一个警告)
    CHARACTER SET [=] charset_name 指定数据库编码方式(DEFAULT可写可不写)

    这里我们简单创建一个数据库vue_chat

    CREATE DATABASE  vue_chat;

    查看数据库,使用:

    SHOW DATABASES;
    
    

     四,使用sequelize链接数据库

     在server目录下新建db.js

    const Sequelize = require('sequelize');
    const sequelize = new Sequelize(
      'vue_chat', // 数据库名
      'root',   // 用户名
      'root',   // 用户密码
      {
          'dialect': 'mysql',  // 数据库使用mysql
          'host': 'localhost', // 数据库服务器ip
          'port': 3306,        // 数据库服务器端口
          'define': {
              // 字段以下划线(_)来分割(默认是驼峰命名风格)
              'underscored': true
          }
      }
    );

    新建一个模型(这里模型对应的就是mysql中的表的概念,这里直接使用我之前定义好的模型,不过多解释模型里面的字段(每个人设计模型或者表的思考方式都会有差异,这个东西根据项目来设计))const account = sequelize.define(

    // tablename
      'account',
      {
        'user_name': {
          'type': Sequelize.STRING,
          'allowNull': false
        },
        'pwd': {
          'type': Sequelize.STRING,
          'allowNull': false
        },
        'email': {
          'type': Sequelize.STRING,
          'allowNull': true
        },
        'avatar': {
          'type': Sequelize.STRING,
          'allowNull': true
        },
        'user_info': {
          'type': Sequelize.STRING,
          'allowNull': true
        },
        'user_id': {
          'type': Sequelize.CHAR(64),
          'allowNull': false,
          'unique': true
        },
        'create_temp': {
          'type': Sequelize.DATE,
          'defaultValue': Sequelize.NOW,
        },
        'user_fans': {
          'type': Sequelize.INTEGER,
          'allowNull': false,
          'defaultValue': 0
        },
        'attention': {
          'type': Sequelize.BIGINT,
          'allowNull': false,
          'defaultValue': 0
        },
        'poetry_num': {
          'type': Sequelize.BIGINT,
          'allowNull': false,
          'defaultValue': 0
        }
      }
    )
    account.sync();
    sequelize.authenticate().then(() => {
      console.log('Connection has been established successfully.');
    }).catch(err => {
      console.error('Unable to connect to the database:', err);
    });
    module.exports
    = sequelize

    新建user.js

    const express = require('express')
    
    const Router = express.Router()
    
    const sequelize = require('./db')
    const account = sequelize.model('account')
    
    const utility  = require('utility')
    
    
    Router.post('/register', function(req, res) {
      // 用户注册
      const body = req.body.userinfo
      const {user_name, pwd} = req.body.userinfo
      const data = {
        user_name: user_name,
        pwd: pwdMd5(pwd),
        create_temp: new Date().getTime(),
        user_id: pwdMd5(Date.now())
      }
      account.create(data).then(doc => {
        const {user_name, user_id, user_info, avatar} = doc
        res.cookie('user_id', user_id)
        return res.json({
          code: 0,
          data: {
            user_name: user_name,
            user_id: user_id,
            user_info: user_info,
            avatar: avatar
          }
        })
      })
    })
    
    module.exports = Router

    此时我们第一个接口也就是注册接口已经写完,接下来就是前后端联调了

    首先先去我们的前端设置请求代理,因为前端服务端口和我们后端服务接口不是同一个,所以存在跨域的问题

    在根目录下找到config文件夹,打开index.js文件进行修改

    proxyTable: {
          '/api': {
            target: 'http://localhost:9094/',
            changeOrigin: true,
            pathRewrite: {
              '^/api': '/'
            }
          }
        },

    紧接着,在我们之前新建好的api文件夹下,新建一个account.js

    import * as axios from '../common/js/axios'
    
    // 用户注册
    const register = params => axios.post('/user/register', params)
    
    export {
      register
    }

    五.对接接口

    打开store中的action.js

    import * as types from './mutation-types'
    import { Loading } from '../Plugins/index'
    import { register} from 'api/account'
    
    const registerAccount = function ({commit, state}, {userinfo}) {
      // 用户注册
      // 这里返回一个Promise函数,方便在组件中知道当前接口是否请求完成
      return new Promise((resolve, reject) => {
        register({userinfo}).then(res => {
          if (res.status === 200 && res.data.code === 0) {
            resolve(res.data.data)
          } else {
            reject(new Error())
          }
        })
      })
    }
    export {
      registerAccount,
    }

    这里假设你已经写好了注册的前端的界面,下面是一个简单的注册界面

     

    js交互假设你已经写好了

    import { mapActions } from 'vuex'
    export default {
      data () {
        return {
          blurstate: false,
          user_name: '',
          pwd: ''
        }
      },
      methods: {
        handlerLogin () {
          if (!this.user_name) {
            this.$toast({
              state: true,
              desc: '请输入用户名'
            })
            return
          }
          if (!this.pwd) {
            this.$toast({
              state: true,
              desc: '请输入密码'
            })
            return
          }
          let userinfo = {
            user_name: this.user_name,
            pwd: this.pwd
          }
          this.userLogin({userinfo}).then(res => {
            if (res.status === 200 && res.data.code === 0) {
              this.$router.push({path: '/'})
            }
          })
        },
        toRgister () {
          this.$router.push({path: '/register'})
        },
        ...mapActions([
          'userLogin'
        ])
      }
    }

    点击注册,这个时候查看我们的数据库是否已经正确写入数据

    切换到我们新建的数据库
    use vue_chat;
    查看数据表
    show tables;
    查看数据表结构;
    desc accounts;
    查看数据表中的数据
    select * from accounts;

    六、登录注册的模型的安全设计

    上面的登录注册只是一个简单的数据增删改查,对于用户的数据没有丝毫安全性可言,只要拦截我们的登录注册接口即可拿到我们的用户密码,那么下图就是我们改造后的登录注册模型

    如上图这个模型,即使我们的登录接口被拦截了,那么也只能拿到一段MD5的加密字符串,根本无法获取我们真实的密码,而且这个加密串根本也和我们的数据库存的加密串是不一致的,所以根本无法破解

  • 相关阅读:
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(13) 线程安全接口和双检查加锁优化
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(15) 监视器对象
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(8) 主动器
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(6) 扩展接口
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(12) 策略化加锁
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(10) 接受器 连接器
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(11) 同步模式与定界加锁
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(7) 事件处理模式与反应器
    《面向模式的软件体系结构2用于并发和网络化对象模式》读书笔记(14) 并发模式和主动对象
    Ubuntu 12.04开机默认启动IBus Anny
  • 原文地址:https://www.cnblogs.com/songdongdong/p/9407887.html
Copyright © 2011-2022 走看看