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

时间:2022-06-08
本文章向大家介绍在线商城项目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