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中增加
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述测试:
注册测试:
在这里插入图片描述
登录测试:在这里插入图片描述
请求当前用户信息测试:在这里插入图片描述

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