登录模板包括登录、登出、购物车数量查询、全局拦截
routes/user.js
引入user模型
var User = require('./../models/user');
登录以后需要将用户信息保存到cookie
在app.js中引入cookie-parser插件,专门处理cookie
var cookieParser = require('cookie-parser');
在app.js中引入body-parser,主要对post请求做json转换
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(cookieParser());
因为有了cookie-parser,我们可以做一些cookie的存取
增加转发
node后端登录 routes/user.js
var express = require('express');
var router = express.Router();
var User = require('./../models/user');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.get('/test', function(req, res, next) {
res.send('test');
});
// 登录
router.post('/login', function(req, res, next) {
// 获取前端传过来的参数 post方式用req.Body形式获取参数
var param = {
userName:req.body.userName,
userPwd:req.body.userPwd
}
User.findOne(param, function(err,doc) {
if(err){
res.json({
status:"1",
msg:err.message
});
}else{
if(doc){
res.cookie("userId",doc.userId,{ // 将用户信息存入cookie
path:'/', // 存储路径
maxAge: 1000*60*60 // 有效时间 单位毫秒
});
res.json({
status:'0',
msg:'',
result:{
userName:doc.userName
}
})
}
}
});
});
module.exports = router;
NavHeader.vue 登录功能
<template>
<header class="header">
<symbol id="icon-cart" viewBox="0 0 38 32">
<title>cart</title>
<path class="path1" d="M37.759 0h-4.133c-0.733 0.004-1.337 0.549-1.434 1.255l-0.546 4.342c-0.081 0.484-0.496 0.849-0.997 0.849-0.005 0-0.009-0-0.014-0h-27.604c-0.003 0-0.007-0-0.011-0-1.674 0-3.031 1.357-3.031 3.031 0 0.34 0.056 0.666 0.159 0.971l2.52 8.062c0.385 1.194 1.486 2.043 2.785 2.043 0.126 0 0.25-0.008 0.372-0.023l22.983 0.002c0.515 0.131 0.626 0.768 0.626 1.283 0.005 0.044 0.009 0.095 0.009 0.146 0 0.501-0.294 0.933-0.718 1.134l-22.439 0.003c-0.354 0-0.642 0.287-0.642 0.642s0.287 0.642 0.642 0.642h22.745l0.131-0.071c0.919-0.392 1.551-1.287 1.551-2.33 0-0.058-0.002-0.116-0.006-0.173 0.021-0.108 0.033-0.24 0.033-0.376 0-1.072-0.732-1.973-1.724-2.23l-23.357-0.004c-0.063 0.008-0.135 0.013-0.209 0.013-0.719 0-1.332-0.455-1.566-1.093l-2.53-8.095c-0.048-0.154-0.076-0.332-0.076-0.515 0-0.973 0.782-1.764 1.752-1.778h27.657c1.159-0.004 2.112-0.883 2.232-2.011l0.547-4.345c0.010-0.083 0.078-0.147 0.161-0.152l4.133-0c0.354 0 0.642-0.287 0.642-0.642s-0.287-0.642-0.642-0.642z"></path>
<path class="path2" d="M31.323 9.69c-0.022-0.003-0.048-0.004-0.074-0.004-0.328 0-0.598 0.248-0.633 0.567l-0.809 7.268c-0.003 0.022-0.004 0.048-0.004 0.074 0 0.328 0.248 0.598 0.567 0.633l0.074 0c0.001 0 0.003 0 0.004 0 0.327 0 0.596-0.246 0.632-0.563l0.809-7.268c0.003-0.022 0.004-0.048 0.004-0.074 0-0.328-0.248-0.598-0.567-0.633z"></path>
<path class="path3" d="M27.514 25.594c-1.769 0-3.203 1.434-3.203 3.203s1.434 3.203 3.203 3.203c1.769 0 3.203-1.434 3.203-3.203s-1.434-3.203-3.203-3.203zM27.514 30.717c-1.060 0-1.92-0.86-1.92-1.92s0.86-1.92 1.92-1.92c1.060 0 1.92 0.86 1.92 1.92s-0.86 1.92-1.92 1.92z"></path>
<path class="path4" d="M9.599 25.594c-1.769 0-3.203 1.434-3.203 3.203s1.434 3.203 3.203 3.203c1.769 0 3.203-1.434 3.203-3.203s-1.434-3.203-3.203-3.203zM9.599 30.717c-1.060 0-1.92-0.86-1.92-1.92s0.86-1.92 1.92-1.92c1.060 0 1.92 0.86 1.92 1.92s-0.86 1.92-1.92 1.92z"></path>
</symbol>
<div class="navbar">
<div class="navbar-left-container">
<a href="/">
<img class="navbar-brand-logo" src="static/logo.png"></a>
</div>
<div class="navbar-right-container" style="display: flex;">
<div class="navbar-menu-container">
<!--<a href="/" class="navbar-link">我的账户</a>-->
<span class="navbar-link"></span>
<span v-text="nickName" v-if="nickName"></span>
<a href="javascript:void(0)" class="navbar-link" @click="loginModalFlag=true" v-if="!nickName">Login</a>
<a href="javascript:void(0)" class="navbar-link" v-if="nickName">Logout</a>
<div class="navbar-cart-container">
<span class="navbar-cart-count"></span>
<a class="navbar-link navbar-cart-link" href="/#/cart">
<svg class="navbar-cart-logo">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-cart"></use>
</svg>
</a>
</div>
</div>
<div class="md-modal modal-msg md-modal-transition" v-bind:class="{'md-show':loginModalFlag}">
<div class="md-modal-inner">
<div class="md-top">
<div class="md-title">Login in</div>
<button class="md-close" @click="loginModalFlag=false">Close</button>
</div>
<div class="md-content">
<div class="confirm-tips">
<div class="error-wrap">
<span class="error error-show" v-show="errorTip">用户名或者密码错误</span>
</div>
<ul>
<li class="regi_form_input">
<i class="icon IconPeople"></i>
<input type="text" tabindex="1" name="loginname" v-model="userName" class="regi_login_input regi_login_input_left" placeholder="User Name" data-type="loginname">
</li>
<li class="regi_form_input noMargin">
<i class="icon IconPwd"></i>
<input type="password" tabindex="2" name="password" v-model="userPwd" class="regi_login_input regi_login_input_left login-input-no input_text" placeholder="Password" @keyup.enter="login">
</li>
</ul>
</div>
<div class="login-wrap">
<a href="javascript:;" class="btn-login" @click="login">登 录</a>
</div>
</div>
</div>
</div>
<div class="md-overlay" v-if="loginModalFlag" @click="loginModalFlag=false"></div>
</div>
</div>
</header>
</template>
<script>
import './../assets/css/login.css'
import axios from 'axios'
export default {
data(){
return{
userName:'admin', // 用户名
userPwd:'123456', // 密码
errorTip:false, // 校验
loginModalFlag:false, // 是否显示遮罩层
nickName:''
}
},
methods: {
login(){ // 登录方法
if(!this.userName || !this.userPwd){
this.errorTip = true;
return;
}
axios.post("/users/login",{
userName:this.userName,
userPwd:this.userPwd
}).then((response)=>{
let res = response.data;
if(res.status=='0'){
this.errorTip = false;
this.loginModalFlag = false;
this.nickName = res.result.userName;
}else{
this.errorTip = true;
}
})
}
}
}
</script>
node登出功能
router/user.js
// 登出接口
router.post("/logout", function (req,res,next) {
res.cookie("userId", "", { // 登出将userId设置为""
path:"/",
maxAge:-1 // 设置位过期
})
res.json({
status:"0",
msg:'',
result:''
})
})
登出vue前端
logOut(){
axios.post("/users/logout").then((response)=>{
let res = response.data;
if(res.status=="0"){
this.nickName = '';
}
})
}
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
登录拦截
在app.js路由之前添加登录拦截
在express框架中只有安装了express-session框架session才可以使用
https://www.npmjs.com/package/express-session
安装 npm install express-session
node express app.js 全局登录拦截
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var ejs = require('ejs');
/** 加载index路由模块 */
var index = require('./routes/index');
/** 加载user路由模块 */
var users = require('./routes/users');
/** 加载商品路由 */
var goods = require('./routes/goods')
var app = express();
// view engine setup
/** 设置访问的目录 设置views页面在哪放着 */
app.set('views', path.join(__dirname, 'views'));
/** 设置引擎是jade引擎 */
app.engine('.html',ejs.__express)
app.set('view engine', 'html');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
/** 安装第三方插件 */
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
/** 设置静态文件目录 path.join方法就是把两个变量连接要一块 __dirnam就是获取当前目录 */
app.use(express.static(path.join(__dirname, 'public')));
/**=== 全局登录拦截 ========================================================================================================= */
app.use(function (req,res,next) {
if(req.cookies.userId){ // 如果登录成功进行下一步
next();
}else{
console.log(`path:${req.path},originalUrl:${req.originalUrl}`);
// req.originalUrl 获取请求路径 req.path 获取请求路径而不考虑参数
if(req.originalUrl=='/users/login' || req.originalUrl=='/users/logout' || req.originalUrl.indexOf('/goods/list')>-1 ){
next();
}else{
// req.originalUrl获取请求路径 如果是登录登出,则不拦截 否则就没法玩了
// 如果未登录访问商品列表也放行
res.json({ // 如果未登录访问其他功能则拦截
status:'10001',
msg:'当前未登录',
result:''
});
}
}
});
/**=== 全局登录拦截end ========================================================================================================= */
/** 表示当我们访问/的时候就去加载index的路由 */
app.use('/', index);
/** 当访问/user的时候,就去访问users的路由 */
app.use('/users', users);
/** 这通过不同的模块和访问地址来加以区分, 这样的化业务模块会做的更加细分 */
app.use('/goods', goods);
// catch 404 and forward to error handler
/** 全局对404的拦截 */
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err); // 如果next拿不到参数它就会用err这个参数,如果拿到的话它就不会用
});
// error handler
/** 对error的处理 */
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'); // 一旦报错以后就会渲染这个error的页面
});
module.exports = app;
node express router/users.js 登录、登出、校验用户信息
var express = require('express');
var router = express.Router();
var User = require('./../models/user');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.get('/test', function(req, res, next) {
res.send('test');
});
// 登录
router.post('/login', function(req, res, next) {
// 获取前端传过来的参数 post方式用req.Body形式获取参数
var param = {
userName:req.body.userName,
userPwd:req.body.userPwd
}
User.findOne(param, function(err,doc) {
if(err){
res.json({
status:"1",
msg:err.message
});
}else{
if(doc){
res.cookie("userId",doc.userId,{ // 将用户信息存入cookie
path:'/',
maxAge: 1000*60*60
});
res.cookie("userName",doc.userName, {
path:'/',
maxAge: 1000*60*60
});
// req.session.user = doc; // 将用户信息存入session
res.json({
status:'0',
msg:'',
result:{
userName:doc.userName
}
})
}
}
});
});
// 登出接口
router.post("/logout", function (req,res,next) {
res.cookie("userId", "", { // 登出将userId设置为""
path:"/",
maxAge:-1 // 设置位过期
})
res.json({
status:"0",
msg:'',
result:''
})
})
// 校验用户信息
router.get("/checkLogin", function (req,res,next) {
if(req.cookies.userId){
res.json({
status:'0',
msg:'',
result: req.cookies.userName || '' // 获取cookeie req.cookies.属性
});
}else{ // 取不到就说明当前没有登录
res.json({
status:'1',
msg:'未登录',
result:''
});
}
})
module.exports = router;
vue 登录登出用户信息校验
<template>
<header class="header">
<symbol id="icon-cart" viewBox="0 0 38 32">
<title>cart</title>
<path class="path1" d="M37.759 0h-4.133c-0.733 0.004-1.337 0.549-1.434 1.255l-0.546 4.342c-0.081 0.484-0.496 0.849-0.997 0.849-0.005 0-0.009-0-0.014-0h-27.604c-0.003 0-0.007-0-0.011-0-1.674 0-3.031 1.357-3.031 3.031 0 0.34 0.056 0.666 0.159 0.971l2.52 8.062c0.385 1.194 1.486 2.043 2.785 2.043 0.126 0 0.25-0.008 0.372-0.023l22.983 0.002c0.515 0.131 0.626 0.768 0.626 1.283 0.005 0.044 0.009 0.095 0.009 0.146 0 0.501-0.294 0.933-0.718 1.134l-22.439 0.003c-0.354 0-0.642 0.287-0.642 0.642s0.287 0.642 0.642 0.642h22.745l0.131-0.071c0.919-0.392 1.551-1.287 1.551-2.33 0-0.058-0.002-0.116-0.006-0.173 0.021-0.108 0.033-0.24 0.033-0.376 0-1.072-0.732-1.973-1.724-2.23l-23.357-0.004c-0.063 0.008-0.135 0.013-0.209 0.013-0.719 0-1.332-0.455-1.566-1.093l-2.53-8.095c-0.048-0.154-0.076-0.332-0.076-0.515 0-0.973 0.782-1.764 1.752-1.778h27.657c1.159-0.004 2.112-0.883 2.232-2.011l0.547-4.345c0.010-0.083 0.078-0.147 0.161-0.152l4.133-0c0.354 0 0.642-0.287 0.642-0.642s-0.287-0.642-0.642-0.642z"></path>
<path class="path2" d="M31.323 9.69c-0.022-0.003-0.048-0.004-0.074-0.004-0.328 0-0.598 0.248-0.633 0.567l-0.809 7.268c-0.003 0.022-0.004 0.048-0.004 0.074 0 0.328 0.248 0.598 0.567 0.633l0.074 0c0.001 0 0.003 0 0.004 0 0.327 0 0.596-0.246 0.632-0.563l0.809-7.268c0.003-0.022 0.004-0.048 0.004-0.074 0-0.328-0.248-0.598-0.567-0.633z"></path>
<path class="path3" d="M27.514 25.594c-1.769 0-3.203 1.434-3.203 3.203s1.434 3.203 3.203 3.203c1.769 0 3.203-1.434 3.203-3.203s-1.434-3.203-3.203-3.203zM27.514 30.717c-1.060 0-1.92-0.86-1.92-1.92s0.86-1.92 1.92-1.92c1.060 0 1.92 0.86 1.92 1.92s-0.86 1.92-1.92 1.92z"></path>
<path class="path4" d="M9.599 25.594c-1.769 0-3.203 1.434-3.203 3.203s1.434 3.203 3.203 3.203c1.769 0 3.203-1.434 3.203-3.203s-1.434-3.203-3.203-3.203zM9.599 30.717c-1.060 0-1.92-0.86-1.92-1.92s0.86-1.92 1.92-1.92c1.060 0 1.92 0.86 1.92 1.92s-0.86 1.92-1.92 1.92z"></path>
</symbol>
<div class="navbar">
<div class="navbar-left-container">
<a href="/">
<img class="navbar-brand-logo" src="static/logo.png"></a>
</div>
<div class="navbar-right-container" style="display: flex;">
<div class="navbar-menu-container">
<!--<a href="/" class="navbar-link">我的账户</a>-->
<span class="navbar-link"></span>
<span v-text="nickName" v-if="nickName"></span>
<a href="javascript:void(0)" class="navbar-link" @click="loginModalFlag=true" v-if="!nickName">Login</a>
<a href="javascript:void(0)" class="navbar-link" @click="logOut" v-if="nickName">Logout</a>
<div class="navbar-cart-container">
<span class="navbar-cart-count"></span>
<a class="navbar-link navbar-cart-link" href="/#/cart">
<svg class="navbar-cart-logo">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-cart"></use>
</svg>
</a>
</div>
</div>
<div class="md-modal modal-msg md-modal-transition" v-bind:class="{'md-show':loginModalFlag}">
<div class="md-modal-inner">
<div class="md-top">
<div class="md-title">Login in</div>
<button class="md-close" @click="loginModalFlag=false">Close</button>
</div>
<div class="md-content">
<div class="confirm-tips">
<div class="error-wrap">
<span class="error error-show" v-show="errorTip">用户名或者密码错误</span>
</div>
<ul>
<li class="regi_form_input">
<i class="icon IconPeople"></i>
<input type="text" tabindex="1" name="loginname" v-model="userName" class="regi_login_input regi_login_input_left" placeholder="User Name" data-type="loginname">
</li>
<li class="regi_form_input noMargin">
<i class="icon IconPwd"></i>
<input type="password" tabindex="2" name="password" v-model="userPwd" class="regi_login_input regi_login_input_left login-input-no input_text" placeholder="Password" @keyup.enter="login">
</li>
</ul>
</div>
<div class="login-wrap">
<a href="javascript:;" class="btn-login" @click="login">登 录</a>
</div>
</div>
</div>
</div>
<div class="md-overlay" v-if="loginModalFlag" @click="loginModalFlag=false"></div>
</div>
</div>
</header>
</template>
<script>
import './../assets/css/login.css'
import axios from 'axios'
export default {
data(){
return{
userName:'admin', // 用户名
userPwd:'123456', // 密码
errorTip:false, // 校验
loginModalFlag:false, // 是否显示遮罩层
nickName:''
}
},
mounted() {
this.checkLogin();
},
methods: {
checkLogin(){
axios.get("/users/checkLogin").then((response)=>{
let res = response.data;
console.log(res);
if(res.status=="0"){
this.nickName = res.result;
}
});
},
login(){ // 登录方法
if(!this.userName || !this.userPwd){
this.errorTip = true;
return;
}
axios.post("/users/login",{
userName:this.userName,
userPwd:this.userPwd
}).then((response)=>{
let res = response.data;
if(res.status=='0'){
this.errorTip = false;
this.loginModalFlag = false;
this.nickName = res.result.userName;
}else{
this.errorTip = true;
}
});
},
logOut(){
axios.post("/users/logout").then((response)=>{
let res = response.data;
if(res.status=="0"){
this.nickName = '';
}
})
}
}
}
</script>