Node接口搭建筆記 (一)

視頻課程地址:https://www.bilibili.com/video/av59056478
資金管理系統帶權限(node/element/vue)

Node接口搭建

express搭建服務器

1.首先在本地新建一個存放項目的文件夾
2.cd到項目文件夾,輸入npm init命令,初始化一個node項目,會生成一個package.json文件,包含了對項目的簡介,並指定了入口文件(“main”: “server.js”,可自己設置其他名稱)
3.在項目根目錄下新建入口文件:server.js
4.搭建本地服務器需要用到express框架,打開終端,輸入 npm install express 安裝即可,安裝完成之後就可以正常使用了
5.

// 引入express
const express = require("express");
// 實例化一個app
const app = express();

// 設置一個端口號,本地環境下是5000
const port = process.env.PORT || 5000;
// 對端口進行監聽
app.listen(port, ()=>{
	console.log(`server running on port ${port}`);
})

完成之後,在控制檯執行 node server.js 可看到輸出信息,這時候它已經將當前的項目運行了,運行之後通過瀏覽器去訪問是訪問不到的,因爲我們沒有設置任何路由。
在這裏插入圖片描述
設置一個路由測試一下:

// 引入express
const express = require("express");
// 實例化一個app
const app = express();

// 設置路由
app.get("/", (req, res) => {
	res.send("Hello World");
})

// 設置一個端口號,本地環境下是5000
const port = process.env.PORT || 5000;
// 對端口進行監聽
app.listen(port, ()=>{
	console.log(`server running on port ${port}`);
})

現在就可以通過瀏覽器來訪問了,但是訪問之前需要重新執行一下 node server.js 纔會生效,因爲我們對代碼做了修改。
在這裏插入圖片描述
這種每次手動執行更新的方式有些繁瑣,我們可以使用nodemon實現在代碼發生改變時自動更新,只需要執行npm install nodemon -g 即可全局安裝
在這裏插入圖片描述

連接MongoDB數據庫

mongodb教程參考:http://www.jspang.com/posts/2017/12/16/mongodb.html

1.在項目中使用本地的mongodb數據庫,在配置之前我們需要開啓本地的mongodb服務在這裏插入圖片描述
2.在根目錄下創建一個config文件夾,新建db.js,用於存放數據庫相關的信息

// 數據庫名稱:node-app-db
module.exports = app => {
 const mongoose = require("mongoose");
 mongoose.connect("mongodb://127.0.0.1:27017/node-app-db",{
  useNewUrlParser: true,
  useUnifiedTopology: true
 }).then(()=>console.log("MongoDB Connected"))
   .catch(error => console.log(error))
}

3.在server.js中引入數據庫的配置

// 搭建服務器
const express = require("express");
// 實例化一個app
const app = express();

// 設置路由
app.get('/', (req, res)=>{
    res.send("Hello World");
})
// 連接數據庫
require('./config/db')(app);

4.保存代碼之後,控制檯會打印如下信息:
在這裏插入圖片描述
說明數據庫已經連接成功了

搭建路由和數據模型並存儲數據到數據庫

路由其實就是我們需要訪問的接口地址。 在項目根目錄下創建文件夾routes->api,然後在api下創建新建文件:users.js,用於編寫與用戶相關的接口。
例:
user.js

const express = require("express");
const router = express.Router();

// $route  GET /api/users/test
// @desc   返回請求的json數據
// @access public(公有接口)
router.get('/test', (req, res)=>{
    res.json({msg:"login works"})
})
module.exports = router;

server.js

const express = require("express");
const app = express();
// 引入user.js
const users = require("./routes/api/users.js");
// 使用路由
app.use("/api/users", users);
// 連接數據庫
require('./config/db')(app);
// 本地環境下是5000
const port = process.env.PORT || 5000;
app.listen(port, ()=>{
 console.log(`server running on port ${port}`);
})

訪問:http://localhost:5000/api/users/test
在這裏插入圖片描述在項目根目錄下創建一個models文件夾,然後新建一個User.js文件,用於存放User數據模型
User.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// crates schema
const UserSchema = new Schema({
    nam:{type: String, required: true},
    email:{type:String, required: true},
    password: {type: String, required: true},
    avatar: {type: String},
    date: {type: Date, default: Date.now}
});
module.exports = User = mongoose.model("users", UserSchema);

安裝一個測試接口的工具: postman
完成後用上面的接口地址測試一下:在這裏插入圖片描述在users.js中寫一個註冊接口,

// @route  POST  api/users/register
// @desc   返回請求的json數據
// @access public接口,如果要返回token的話則是私有接口
router.post('/register', (req, res)=>{
    console.log(req.body);
})

它是一個post請求,需要安裝一個第三方模塊body-parser

npm install body-parser

然後在server.js中引入

const bodyParser = require("body-parser");
// 使用bodyParser中間件
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

urlencoded是爲了解決post請求下的x-www-form-urlencoded
在這裏插入圖片描述
測試一下接口:
在這裏插入圖片描述
因爲沒有返回內容,所以在postman的控制檯看不到信息,但在終端可以看到打印的信息:
在這裏插入圖片描述

新增需求: 查詢郵箱是否存在,如果註冊的郵箱已在數據庫中存在,則返回相應的錯誤提示;否則成功添加到數據庫中
一些準備:
用戶的密碼加密,需要一個第三方插件:npm install bcrypt

在users.js中加入代碼:

const User = require("../../models/User.js");
const bcrypt = require("bcrypt"); // 加密

// @route  POST  api/users/register
// @desc   返回請求的json數據
// @access public接口,如果要返回token的話則是私有接口
router.post('/register', (req, res)=>{
    // 查詢數據庫該郵箱是否存在
    User.findOne({email: req.body.email})
        .then((user) => {
            if(user){
            	return res.status(400).json("郵箱已被註冊!")
            } else {
            	const newUser = new User({
            	    name: req.body.name,
            	    email:req.body.name,
            	    password:req.body.password
            	});
            	bcrypt.genSalt(10, function(err, salt){
            	    bcrypt.hash(newUser.password, salt, (err, hash)=>{
            	        if(err) throw err;
            	        newUser.password = hash; // hash是已經加密後的密碼
            	        newUser.save()
            	               .then(user=>res.json(user))
            	               .catch(err=>console.log(err));
            	    })
            	})
            }
        })
})

測試:
第一次提交在這裏插入圖片描述
再次提交:
在這裏插入圖片描述
查看數據庫:
在這裏插入圖片描述
數據已經成功保存了

使用全球公認頭像gravatar

參考:https://www.npmjs.com/search?q=gravatar
安裝:npm install gravatar
在users.js中引入

const gravatar = require('gravatar');
......
// 郵箱未被註冊,則提交用戶的相關信息
......
    const avatar = gravatar.url(req.body.email, {s:'200', r:'pg', d: 'mm'});
    const newUser = new User({
     name: req.body.name,
     email:req.body.email,
     avatar, // 頭像
     password:req.body.password,
    });
......

測試:
在這裏插入圖片描述
複製avatar的地址訪問之後會得到一個圖片,這就是"mm"返回給我們的圖片,如果在gravatar註冊了這個郵箱的話,則會返回在gravatar網站中使用的頭像圖片

搭建登錄接口

參考:https://www.npmjs.com/search?q=bcrypt
安裝:npm install bcrypt (可用於密碼匹配)
users.js中添加登錄接口代碼:

// @route  POST  api/users/login
// @desc   返回token (會用到jwt passport)
// @access public接口,如果要返回token的話則是私有接口
router.post('/login', (req, res)=>{
    const email = req.body.email;
    const name = req.body.name;
    const password = req.body.password;
    // 查詢數據庫
    User.findOne({email:email})
        .then(user=>{
            if(!user){
                return res.status(404).json({"email": "用戶不存在"});
            }
            // 密碼匹配
            bcrypt.compare(password, user.password)
                  .then(isMatch=>{
                      if(isMatch){
                          res.json({"msg":"success"});
                      } else {
                          return res.status(404).json({"password": "密碼錯誤"})
                      }
                  
                  })
        })
})

測試:可根據不同的情況填寫參數進行測試
在這裏插入圖片描述修改代碼,使得登錄成功之後返回的是token
參考:https://www.npmjs.com/package/jsonwebtoken
安裝:npm install jsonwebtoken
加密名稱單獨設置一個文件keys.js放在config文件夾下
keys.js

module.exports = {
 secretOrKey:"secret"
};

密碼匹配部分做些修改:

const jwt = require('jsonwebtoken');
const keys = require("../../config/keys.js");
......
// 密碼匹配
bcrypt.compare(password, user.password)
      .then(isMatch => {
          if(isMatch){
              // jwt.sign("規則","加密名稱","過期時間","箭頭函數")
              const rule = {
                 id:user.id,
                 name:user.name,
                 avatar:user.avatar
              };
              jwt.sign(rule, keys.secretOrKey, {expiresIn:3600},(err, token)=>{
                  if(err) throw err;
                  res.json({
                      success:true,
                      token:"wu"+token
                  });
              })
          }else{
              return res.status(400).json({"password": "密碼錯誤"});
          }
      })

測試:
在這裏插入圖片描述

使用passport-jwt驗證token

token可以理解令牌,或者說鑰匙。通過用戶名和密碼登錄之後會返回一個token,可以拿着這個token去請求一些數據。如果沒有這個token或者token已經過期的話,就得不到想要的數據了。
參考:
https://www.npmjs.com/package/passport-jwt https://www.npmjs.com/package/passport

安裝:npm install passport-jwt passport (用於驗證token)
在users.js中引入:

const passport = require("passport");

在server.js中對passport進行初始化(初始化之後纔可以被使用)

// passport的初始化
app.use(passport.initialize());

還需要對passport進行一些配置,單獨建一個passport.js文件放在config下:
passport.js

const JwtStrategy = require("passport-jwt").Strategy,
      ExtractJwt = require("passport-jwt").ExtractJwt;
const mongoose = require("mongoose");
const User = mongoose.model("users"); // 數據庫表的名字
const keys = require("../config/keys.js");

const opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;

module.exports = passport => {
passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
        console.log(jwt_payload);
    }));
}

配置完成後還需要在server.js中引入

const passport = require("passport");
......
// passport的初始化
app.use(passport.initialize());
require('./config/passport.js')(passport);

在users.js中加入token驗證:

// @route  POST  api/users/current
// @desc   返回當前用戶的信息
// @access private
// router.get("/current", "驗證token", "箭頭函數")
router.get("/current", passport.authenticate("jwt", {session:false}), 
   (req, res)=>{
      res.json({msg: "success"});
});

測試
在這裏插入圖片描述
返回的是一個"Unauthorized", 原因是請求的時候沒有給它添加token。
現在使用一個有效賬號登錄之後,複製得到的token值,在請求頭中加入token
在這裏插入圖片描述
點擊send之後得到的還是"Unauthorized",返回的token值的前綴一定要是一個固定的名字,名稱已經配置好了,必須是"Bearer "

// token:"wu"+token
// 修改爲
token:"Bearer "+token

重新登錄獲取新的token值,填入請求頭中,再點擊send可在終端看到打印信息(沒有返回值,所在postman的控制檯看不到):
在這裏插入圖片描述修改一下passport.js

module.exports = passport => {
 passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
     // console.log(jwt_payload);
     User.findOne({id: jwt_payload.sub}, (err, user) => {
         User.findById(jwt_payload.id)
          .then(user => {
              if(user){
                 return done(null, user);
              }
              return done(null, false);
          })
          .catch(err => console.log(err));
     });
 }));
}

修改一下users.js:

// @route  POST  api/users/current
// @desc   返回當前用戶的信息
// @access private
// router.get("/current", "驗證token", "箭頭函數")
router.get("/current", passport.authenticate("jwt", {session:false}), 
    (req, res)=>{
       res.json({
          id:req.user.id,
          name:req.user.name,
          email:req.user.email
    });
});

測試:在這裏插入圖片描述

增加身份字段及接口調試

在之後的項目中,會有關於用戶身份的區別,所以我們需要再增加一個身份字段identity
models/User.js中增加
在這裏插入圖片描述
routes/api/users.js中增加
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述測試:
註冊測試:
在這裏插入圖片描述
登錄測試:在這裏插入圖片描述
請求當前用戶信息測試:在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章