node-express通過jwt實現帶token驗證的登錄

文件目錄

│  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')
  }
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章