在线商城项目17-登录态保持

简介

前面我们实现了登入登出,一切看上去是没有什么问题,但是如果我们试着在登录情况下刷新一下页面。

头部显示变成了未登录的情况,如果每次刷新或者进入新的页面用户都需要重新登录,明显是不友好的,我们需要在用户登录以后保持登录态一段时间。可是,http本身又是无状态无连接的,此时我们需要借助cookie和session。关于这两者的详细知识我今后会开单章说明,不明白的同学可以先网上搜集一些资料看看。

本节主要有如下工作:

  1. 保持登录态
  2. 登出逻辑实现

1. 保持登录态

step1 在server端下载express-session包

npm install express-session --save

step2 在server端引入并使用express-session 修改app.js文件如下:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var goodsRouter = require('./routes/goods');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
// session需要在定义路由前使用
app.use(session({
    secret: 'six-tao',
    name: 'ST-TOKEN',
    cookie: {maxAge: 5 * 60 * 1000},
    resave: true,
    saveUninitialized: false
}))
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/goods', goodsRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

step3 修改users.js逻辑 在login接口中,增加登陆成功后将doc保存到req.session.user的逻辑,增加登录状态判断逻辑。如下:

var express = require('express');
var router = express.Router();
var User = require('../models/user');

/* post users info. */
router.post('/login', function (req, res, next) {
    console.log(req.body);
    let param = {
        userName: req.body.userName,
        userPwd: req.body.userPwd
    };
    if (req.session.user) {
        res.json({
            code: '101',
            msg: '您已登录'
        });
        return;
    }
    User.findOne(param, function (err, doc) {
        if (err) {
            res.json({
                code: '900',
                msg: err.message || '服务器错误'
            })
        } else {
            if (doc) {
                req.session.user = doc
                res.json({
                    code: '000',
                    msg: '',
                    result: {
                        userName: doc.userName
                    }
                });
            } else {
                res.json({
                    code: '102',
                    msg: '用户名或密码错误'
                });
            }
        }
    });
});

router.get('/checkLogin', function (req, res, next) {
    console.log(req.session.user)
    if (req.session.user) {
        res.json({
            code: '000',
            msg: '',
            result: req.session.user
        });
    } else {
        res.json({
            code: '102',
            msg: '未登录',
        });
    }
})

module.exports = router;

step4 修改前端逻辑 在main.js中增加登录状态判断逻辑:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import axios from 'axios'
import VueLazyLoad from 'vue-lazyload'

import './assets/css/base.css'
import './assets/css/login.css'
import './assets/css/product.css'

Vue.config.productionTip = false

Vue.use(VueLazyLoad, {
  loading: '../static/loading/loading-bars.svg',
  error: '../static/ok-2.png'
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>',
  created () {
    this.checkLogin()
  },
  methods: {
    checkLogin () {
      axios.get('/api/users/checkLogin').then(res => {
        let data = (res && res.data) || {}
        if (data.code === '000') {
          let result = data.result || {}
          this.$store.commit('LOG_IN', {userName: result.userName})
        }
      })
    }
  }
})

我们检测一下结果: 跳登录页,输入错误的账号密码:

输入正确的账号密码:

登录状态下刷新:

2. 登出逻辑实现

之前我们把登出逻辑放在前端。我们看一下:

刷新以后会出现问题。我们把登出的前后端逻辑补齐。

step1 后端逻辑 在users.js增加如下代码:

router.post('/logout', function (req, res, next) {
    req.session.destroy();
    res.json({
        code: '000',
        msg: '登出成功'
    });
});

step2 前端逻辑 修改PageHead.vue的logout方法如下

    logout () {
      axios.post('/api/users/logout').then(res => {
        let data = (res && res.data) || {}
        if (data.code === '000') {
          this.$store.commit('LOG_OUT')
        }
      })
    }

我们重新运行项目,并登陆以后:

six-tao-1706.gif

总结

到这里,我们的登录逻辑就算基本完成了。当然,真实的项目中,逻辑不止这么简单。比如我们这里的密码使用明文存储,是非常危险的,密码应该加密加盐处理。另外,我们重启服务器的时候session失效了,可以将session放在redis或者mongodb中进行存储。等等。 我们提交一下代码:

  1. six-tao
git status
git diff
git commit -am 'add checkLogin and logout'
git push
  1. six-tao-server
git status
git diff
git commit -am 'add session, checkLogin and logout'
git push

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏网络

代理工具shadowProxy之神出鬼没的切换IP地址

前言 在渗透测试过程中,往往会遇到特别“小气”的目标,稍微碰一下就封IP。这种情况下,我们很自然的想到通过网上大量的免费代理进行IP隐匿。 那么问题来了,难道拿...

3428
来自专栏开发与安全

中断机制和中断描述符表、中断和异常的处理

注:本分类下文章大多整理自《深入分析linux内核源代码》一书,另有参考其他一些资料如《linux内核完全剖析》、《linux c 编程一站式学习》等,只是为了...

2510
来自专栏糊一笑

react脚手架改造(react/react-router/redux/eslint/karam/immutable/es6/webpack/Redux DevTools)

公司突然组织需要重新搭建一个基于node的论坛系统,前端采用react,上网找了一些脚手架,或多或少不能满足自己的需求,最终在基于YeoMan的react脚手架...

3585
来自专栏Brian

Mac 配置终端环境

Mac 配置终端开发环境 ---- 概述 作为一个服务端开发人员基本上都是通过终端和服务器打交道,所以一个好个开发人员那么他的终端配置也是高效的。“工欲善事必先...

43411
来自专栏Porschev[钟慰]的专栏

Windows Server 2008 R2 配置Exchange 2010邮件服务器并使用EWS发送邮件

配置环境 配置环境完全在此前一篇文章搭建好的环境下进行配置: http://www.cnblogs.com/zhongweiv/archive/201...

4648
来自专栏Felix的技术分享

《一个操作系统的实现》笔记(2)--保护模式

3698
来自专栏乐沙弥的世界

cannot set user id: Resource temporarily unavailable

    前阵子,Infra报告无法透过putty以及SecureCRT连接到数据库服务器,提示的错误为Resource temporarily unavaila...

760
来自专栏Golang语言社区

gRPC服务发现&amp;负载均衡

构建高可用、高性能的通信服务,通常采用服务注册与发现、负载均衡和容错处理等机制实现。根据负载均衡实现所在的位置不同,通常可分为以下三种解决方案:

7172
来自专栏菩提树下的杨过

ActiveMQ笔记(6):消息延时投递

在开发业务系统时,某些业务场景需要消息定时发送或延时发送(类似:飞信的短信定时发送需求),这时候就需要用到activemq的消息延时投递,详细的文档可参考官网说...

3355
来自专栏Android机动车

Android BLE 快速上手指南

本文旨在提供一个方便没接触过Android上低功耗蓝牙(Bluetooth Low Energy)的同学快速上手使用的简易教程,因此对其中的一些细节不做过分深入...

1342

扫码关注云+社区

领取腾讯云代金券