文章目錄
文件目錄
│ package-lock.json
│ package.json
│ server.js
│
├─config//配置文件
│ key.js
│ passport.js
│
├─models//實例
│ Profile.js
│ User.js
│
└─routers
└─api
profile.js//產品api
users.js//用戶登錄api
啓動項目
在package.json中
{
"name": "node_app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node server.js",//server.js爲入口啓動文件
"serve": "nodemon server.js"
},
"author": "amos",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"express": "^4.17.1",
"gravatar": "^1.8.0",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.9.3",
"nodemon": "^2.0.2",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"tree": "^0.1.3"
}
}
npm run serve //通過nodemon啓動server.js
入口文件-server.js
const express = require('express');//引入express模塊
const app = express();//後續可以通過app.xxx()調用express組件
連接MongoDB
const mongoose = require('mongoose');
mongoose.set('useFindAndModify', false)
//DB config
const db = require('./config/key').mongoURL;
//db connection
mongoose.connect(db, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("MongoDB connected");
}).catch(() => {
console.log(err);
})
中間件
const bodyParser = require('body-parser');
const passport = require('passport');
const users = require('./routers/api/users');
const profile = require('./routers/api/profile');
//body-parser
// parse application/x-www-form-urlencoded
/*
就是application/x-www-from-urlencoded,會將表單內的數據轉換爲鍵值對,&分隔。
當form的action爲get時,瀏覽器用x-www-form-urlencoded的編碼方式,將表單數據編碼爲
(name1=value1&name2=value2…),然後把這個字符串append到url後面,用?分隔,跳轉
到這個新的url。
當form的action爲post時,瀏覽器將form數據封裝到http body中,然後發送到server。
這個格式不能提交文件。
*/
app.use(bodyParser.urlencoded({
extended: false
}));
// parse application/json
app.use(bodyParser.json());
//routers中間件
app.use('/api/users', users);
app.use('/api/profile', profile);
//passport初始化
app.use(passport.initialize());
require('./config/passport')(passport);
routers/api/user.js中的login方法
// $route POST api/users/login
// @desc 返回token jwt passport
// @access public
router.post(('/login'), (req, res) => {
//接收url後面跟的數據
const email = req.body.email;
const password = req.body.password;
//查詢數據庫
User.findOne({
email
})
.then(user => {
if (!user) {
return res.status(404).json("用戶不存在");
}
//密碼匹配 之前用的genSalt加密 現在使用compare匹配密碼
// Load hash from your password DB.
bcrypt.compare(password, user.password)
.then(isMatch => {
if (isMatch) {
//sign 第一個參數是規則 第二個參數是加密名字 第三個是過期時間 第四個是箭頭函數
const rule = {
id: user.id,
name: user.name,
avatar: user.avatar,
identity: user.identity
};
jwt.sign(rule, keys.secreteOrKey, {
expiresIn: 3600
}, (err, token) => {
if (err) throw err;
res.json({
success: true,
token: "Bearer " + token
})
})
// res.json({
// msg: "success"
// });
} else {
return res.status(400).json("密碼錯誤");
}
})
}).catch(err => console.log(err));
})
前端接收到token之後
this.$axios.post('/api/users/login', this.loginUser)
.then(res => {
//登錄成功,獲取tokentoken
const {
token
} = res.data;
//存儲到localStorage
localStorage.setItem('eleToken', token);
//解析token
const decoded = jwt_decode(token);
// console.log(decoded);
//token存儲到vuex中
this.$store.dispatch('setAuthenticated', !this.isEmpty(decoded));
this.$store.dispatch('setUser', decoded);
// console.log(this.$store);
this.$router.push('./index')
this.$message({
message: '登錄成功!',
type: 'success'
})
})
Vue的vuex-actions
const actions = {
setAuthenticated: ({
commit
}, isAuthenticated) => {
commit(types.SET_AUTHENTICATED, isAuthenticated);
},
setUser: ({
commit
}, user) => {
commit(types.SET_USER, user);
},
clearCurrentState: ({
commit
}) => {
commit(types.SET_AUTHENTICATED, false);
commit(types.SET_USER, null)
}
}
在router的index.js中設置路由守衛
router.beforeEach((to, from, next) => {
const isLogin = localStorage.eleToken ? true : false;
if (to.path == '/login' || to.path == '/register') {
next();
} else {
isLogin ? next() : next('/login')
}
})