日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

基于Node的PetShop,RESTful API以及认证

發(fā)布時(shí)間:2023/12/31 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Node的PetShop,RESTful API以及认证 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前篇 - 基本認(rèn)證,用戶(hù)名密碼
后篇 - OAuth2 認(rèn)證

由于寵物店的業(yè)務(wù)發(fā)展需要,我們需要一種更加便捷的方式來(lái)管理日益增多的寵物和客戶(hù)。最好的方法就是開(kāi)發(fā)一個(gè)APP,我可以用這個(gè)APP來(lái)添加、更新和刪除寵物。同時(shí),業(yè)務(wù)要給寵物店的會(huì)員用戶(hù)有限查看某些寵物。

我們?cè)陂_(kāi)發(fā)中會(huì)用到NodeJs以及基于NodeJs的開(kāi)發(fā)框架,如:Express,Mongoose(用來(lái)管理MongoDB的數(shù)據(jù)),Passport(認(rèn)證)等工具。項(xiàng)目代碼在這里。

開(kāi)始

我們這個(gè)項(xiàng)目的結(jié)構(gòu)大概是這樣的:

petshot/ //服務(wù)端和客戶(hù)端(android)server/ //服務(wù)端models/ //實(shí)體類(lèi)pet.jsuser.jsnode_modules/ //npm安裝的包,無(wú)需手動(dòng)修改package.json //project定義和依賴(lài)聲明 server.js //服務(wù)端的一切從這里開(kāi)始

注意:node_modules這個(gè)目錄你不需要?jiǎng)?chuàng)建,在執(zhí)行npm安裝命令之后這個(gè)目錄會(huì)自動(dòng)生成,并且npm命令會(huì)自動(dòng)管理這個(gè)目錄。

定義項(xiàng)目和依賴(lài)的包

這里假設(shè)你已經(jīng)跳轉(zhuǎn)到petshop/server/目錄下了。之后在Terminal里執(zhí)行命令:

npm init

按照提示,依次在Terminal里輸入相應(yīng)的信息。最后npm命令生成package.json文件。文件是這樣的:

{"name": "petshop-server","version": "0.1.0","description": "petshop nodejs server","main": "server.js","dependencies": {} }

內(nèi)容很多,這里是一部分。

安裝所需要的包

為什么NodeJs能讓那么多的開(kāi)發(fā)者青睞有加,npm命令絕對(duì)也是一個(gè)數(shù)得上的原因了。下面就體會(huì)一下,npm命令。

首先,使用npm命令安裝Express:

npm install --save express

npm命令會(huì)選擇合適的Express版本下載安裝在本地。其他的包也是這么安裝的。非常簡(jiǎn)單。

運(yùn)行Server

有了Express,Server就已經(jīng)可以運(yùn)行起來(lái)了。如果你還沒(méi)有創(chuàng)建server.js,請(qǐng)創(chuàng)建。在server.js中添加如下的代碼:

// 引入我們需要的包express var express = require('express'); // 創(chuàng)建一個(gè)express的server var app = express(); // server運(yùn)行的端口號(hào) var port = process.env.PORT || '3090'; // 使用express的路由器 var router = express.Router(); // 訪問(wèn)http://localhost:3090/api的時(shí)候, // 返回一個(gè)json router.get('/', function (req, res) {res.json({'message': '歡迎來(lái)到寵物商店'}); });// 給路由設(shè)定根路徑為/api app.use('/api', router); // 運(yùn)行server,并監(jiān)聽(tīng)指定的端口 app.listen(port, function () {console.log('server is running at http://localhost:3090'); });

通過(guò)require得到的express,就可以初始化出一個(gè)express的server。之后指定路由,并指定路由的相對(duì)根路徑。在app上調(diào)用listen方法,并指定端口。這樣express的server就運(yùn)行起來(lái)了。

在Terminal中輸入命令:

node server.js

測(cè)試一下我們的第一個(gè)server是否可以運(yùn)行。在瀏覽器中輸入地址:*http://localhost:3090/api*就可以看到運(yùn)行結(jié)果了。

幾個(gè)工具

為了開(kāi)發(fā)的更加方便,僅僅以上介紹的內(nèi)容是不夠的。比如,修改代碼之后,使用命令node server.js來(lái)重啟server。設(shè)置斷點(diǎn),單步調(diào)試等。我們來(lái)看看這幾個(gè)工具:

1. Visual Code

微軟改邪歸正依賴(lài)的第一個(gè)靠譜的工具。正好這個(gè)工具非常好的支持了NodeJs的開(kāi)發(fā)。Visual Code還默認(rèn)繼承了Git代碼管理工具。這讓我非常愿意多安利幾句。

并且使用visual code可以非常方便的調(diào)試。比如,設(shè)置斷點(diǎn)、單步調(diào)試,step in、step out等都可以。還可以鼠標(biāo)懸浮查看變量值等。

2. Postman

postman有chrome瀏覽器版本的應(yīng)用,這樣無(wú)論你在什么平臺(tái)上開(kāi)發(fā)只要安裝了Chrome瀏覽器就可以裝一個(gè)postman。這個(gè)工具是用來(lái)檢查RESTful API的。直接使用瀏覽器得出來(lái)的Json字符串有的時(shí)候沒(méi)有格式化,或者格式化不充分,非常難閱讀。

并且直接使用瀏覽器沒(méi)法模擬Http post請(qǐng)求。而Postman很好的解決了以上問(wèn)題。所以,開(kāi)發(fā)必備神器之一postman,你值得擁有。

MongoDB

業(yè)界著名的非關(guān)系數(shù)據(jù)庫(kù)MongoDB。我們?cè)趐etshot的server端使用該庫(kù)來(lái)存儲(chǔ)數(shù)據(jù)。請(qǐng)按照官網(wǎng)說(shuō)明下載安裝(其實(shí)就是把編譯好的二進(jìn)制文件放到一個(gè)指定目錄)。

數(shù)據(jù)庫(kù)安裝好之后,就需要連接數(shù)據(jù)庫(kù)的框架了。這就需要用到mongoose。Mongoose是處理MongoDB的一個(gè)ORM框架。

npm install --save mongoose

安裝好之后在代碼中引入(require)。

var express = require('express'); var mongoose = require('mongoose');

連接到數(shù)據(jù)庫(kù):

// 連接數(shù)據(jù)庫(kù) mongoose.connect('mongodb://localhost:27017/petshot');

創(chuàng)建model

MVC的開(kāi)發(fā)模式這里就不再科普了。凡是MVC模式下開(kāi)發(fā),就一定會(huì)有Model,MVC的M。一般每一個(gè)model都和數(shù)據(jù)庫(kù)中的一個(gè)“表”對(duì)應(yīng),在mongodb里“表”正式名稱(chēng)為“Collection”。我們這里只使用英文,專(zhuān)有名詞沒(méi)必要翻譯。而“表”里的每一條“記錄”又叫做“Document”。

我們首先在petshop/server/models/目錄下新建一個(gè)文件pet.js。之后添加如下代碼:

// 1. 引入mongoose var mongoose = require('mongoose');var Schema = mongoose.Schema; // 2. 定義了Pet的Schema var petSchema = new Schema({name: {type: String, required: true},type: {type: String, required: true},quantity: Number }); // 3. 定義并export了一個(gè)Model module.exports = mongoose.Model('pet', petSchema);

相關(guān)解釋:

  • 引入mongoose庫(kù)。
  • 定義了一個(gè)mongoose的Schema,這個(gè)Schema和一個(gè)mongodb的collection的定義相對(duì)應(yīng)。這個(gè)schema有兩個(gè)字符串和一個(gè)數(shù)字類(lèi)型的屬性。
  • 把mongoose的Model export出去給server端的其他代碼使用。哪里使用哪里就require這個(gè)model。
  • 準(zhǔn)備接收HTTP數(shù)據(jù)

    首先,需要一個(gè)包(package)來(lái)解析http發(fā)送過(guò)來(lái)的數(shù)據(jù)。那么安裝之:

    npm install --save body-parser

    在代碼中引入:

    var express = require('express'); var mongoose = require('mongoose'); // 稍后處理數(shù)據(jù)使用 var Pet = require('./models/pet'); // 解析http數(shù)據(jù) var bodyParser = require('body-parser');

    下面還需要設(shè)置body-parser:

    var app = express();app.use(bodyParser.urlencoded({extended: true }));

    添加些許寵物

    我們的server終于迎來(lái)可以使用的一個(gè)功能了:給寵物商店添加寵物。

    router.get('/', function (req, res) {res.json({'message': '歡迎來(lái)到寵物商店'}); });var petRouter = router.route('/pets');petRouter.post(function (req, res) {var pet = new Pet();pet.name = req.body.name;pet.type = req.body.type;pet.quantity = req.body.quantity;pet.save(function (err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});}); });

    我們?cè)黾恿艘粋€(gè)/pets的相對(duì)路徑來(lái)處理POST請(qǐng)求,并在請(qǐng)求中獲取信息,把用這個(gè)信息來(lái)給初始化的pet的model賦值,并調(diào)用這個(gè)model的save方法保存數(shù)據(jù)到數(shù)據(jù)庫(kù)。

    打開(kāi)postman,各個(gè)設(shè)置如圖:

    這樣就可以往數(shù)據(jù)庫(kù)添加pet數(shù)據(jù)了。

    重構(gòu)代碼

    現(xiàn)在的代碼雖然已經(jīng)可以添加寵物寶寶了。但是,后面如果我們還要添加其他功能,比如:查找,更新和刪除等的時(shí)候,server.js文件勢(shì)必會(huì)不斷增加。這樣給以后代碼的維護(hù)帶來(lái)困擾。所以我們要重構(gòu)代碼。

    在petshop/server/目錄下添加controllers目錄。根據(jù)MVC的模式開(kāi)發(fā),把處理業(yè)務(wù)方面的代碼都存放在某個(gè)controller里。新建pet.js文件。這個(gè)文件就作為pet的controller。并將寵物的增刪改查都放在這個(gè)文件中處理:

    var Pet = require('../models/pet');var postPets = function(req, res) {var pet = new Pet();pet.name = req.body.name;pet.type = req.body.type;pet.quantity = req.body.quantity;pet.save(function (err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});}); };var getPets = function(req, res) {Pet.find(function (err, pets) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pets});}); };var getPet = function(req, res) {Pet.findById(req.params.pet_id, function (err, pet) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});}); };var updatePet = function(req, res) {Pet.findById(req.params.pet_id, function(err, pet) {if (err) {res.json({message: 'error', data: err});return;}pet.quantity = req.params.quantity;pet.save(function (err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});});}); };var deletePet = function(req, res) {Pet.findByIdAndRemove(req.params.pet_id, function(err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: {}});}); }module.exports = {postPets: postPets,getPets: getPets,getPet: getPet,updatePet: updatePet,deletePet: deletePet };

    原來(lái)的server.js也需要重構(gòu):

    var Pet = require('../models/pet');var postPets = function(req, res) {var pet = new Pet();pet.name = req.body.name;pet.type = req.body.type;pet.quantity = req.body.quantity;pet.save(function (err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});}); };var getPets = function(req, res) {Pet.find(function (err, pets) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pets});}); };var getPet = function(req, res) {Pet.findById(req.params.pet_id, function (err, pet) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});}); };var updatePet = function(req, res) {Pet.findById(req.params.pet_id, function(err, pet) {if (err) {res.json({message: 'error', data: err});return;}pet.quantity = req.params.quantity;pet.save(function (err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: pet});});}); };var deletePet = function(req, res) {Pet.findByIdAndRemove(req.params.pet_id, function(err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: {}});}); }module.exports = {postPets: postPets,getPets: getPets,getPet: getPet,updatePet: updatePet,deletePet: deletePet };

    認(rèn)證

    我們當(dāng)讓不行讓誰(shuí)都可以添加寵物寶寶了。查看是可以的,添加需要控制。

    passport

    Passport就是給基于Express開(kāi)發(fā)的web應(yīng)用的,專(zhuān)注于認(rèn)證中間件。也有和body-parser相類(lèi)似的使用方法。passport的功能非常豐富,不過(guò)我們先使用最簡(jiǎn)單的一種認(rèn)證策略。

    安裝:

    npm install --save passport-http

    認(rèn)證以前首先要有用戶(hù)數(shù)據(jù)。

    同時(shí)還有一個(gè)包需要安裝:

    npm install --save bcrypt-nodejs

    這個(gè)包是用來(lái)給密碼hash用的。

    用戶(hù)model

    所有關(guān)于用戶(hù)的數(shù)據(jù)都放在MongoDB的user colleciton里,并有user model與之對(duì)應(yīng)。在models目錄下新建user.js文件。

    var mongoose = require('mongoose'),bcrypt = require('bcrypt-nodejs');var Schema = mongoose.Schema;var userSchema = new Schema({username: {type: String, unique: true, required: true},password: {type: String, required: true} });// * called before 'save' method. userSchema.pre('save', function (next) {var self = this;if (!self.isModified('password')) {return next();}bcrypt.genSalt(5, function (err, salt) {if (err) {return next(err);}bcrypt.hash(self.password, salt, null, function (err, hash) {if (err) {return next(err);}self.password = hash;next();});}); });module.exports = mongoose.model('User', userSchema);

    使用userSchema.pre('save', function(next){})給model添加了一個(gè)在save方法調(diào)用之前先執(zhí)行的方法。在這個(gè)方法里首先檢查用戶(hù)的密碼是否有修改,如果有則使用包bcrypt-nodejs來(lái)hash用戶(hù)的密碼。

    User Controller

    有了model,就需要對(duì)應(yīng)的controller來(lái)處理。在controllers目錄下新建一個(gè)user.js文件作為user controller。注意:實(shí)際開(kāi)發(fā)的時(shí)候你肯定是不會(huì)把全部用戶(hù)的信息都發(fā)到客戶(hù)端的,里面包含了hash的用戶(hù)密碼。

    var User = require('../models/user');var postUsers = function (req, res) {var user = new User({username: req.body.username,password: req.body.password});user.save(function (err) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: user});}); };var getUsers = function (req, res) {User.find(function (err, users) {if (err) {res.json({message: 'error', data: err});return;}res.json({message: 'done', data: users});}); };module.exports = {postUsers: postUsers,getUsers: getUsers };

    定義user controller的路由:

    ...var petController = require('./controllers/pet')userController = require('./controllers/user');...// path: /users, for users router.route('/users').post(userController.postUsers).get(userController.getUsers);

    你已經(jīng)可以在這個(gè)路徑:*http://localhost:3090/api/users*下POST添加用戶(hù),GET獲取全部用戶(hù)。

    認(rèn)證

    在開(kāi)始以前首先確保你已經(jīng)安裝了認(rèn)證需要的包:

    npm install --save passport npm install --save passport-http

    之后給在user model里添加一個(gè)方法驗(yàn)證password:

    userSchema.methods.verifyPassword = function (password, callback) {bcrypt.compare(password, this.password, function (err, match) {if (err) {return callback(err);}callback(null, match);}); };

    接下來(lái),在controllers目錄下添加auth.js文件。

    var passport = require('passport'),BasicStrategy = require('passport-http').BasicStrategy,User = require('../models/user');passport.use(new BasicStrategy(function(username, password, done) {User.findOne({username: username}, function(err, user) {if (err) {return done(err);}// 用戶(hù)不存在if (!user) {return done(null, false);}// 檢查用戶(hù)的密碼user.verifyPassword(passowrd, function(err, match) {// 密碼不匹配if (!match) {return done(null, false);}// 成功return done(null, user);});});} ));module.exports.isAuthenticated = passport.authenticate('basic', {session: false});

    我們使用包passport-http的BasicStrategy來(lái)處理http的用戶(hù)認(rèn)證。首先,我們通過(guò)用戶(hù)名查找用戶(hù)。如果用戶(hù)存在,接著驗(yàn)證用戶(hù)的密碼是否與數(shù)據(jù)庫(kù)的數(shù)據(jù)一致。如果以上兩步通過(guò)驗(yàn)證則用戶(hù)認(rèn)證成功,否則不成功。

    最后一句就是告知passport使用BasicStrategy來(lái)認(rèn)證用戶(hù)。session為false,是告訴passport不存儲(chǔ)用戶(hù)的session。用戶(hù)每一次的http請(qǐng)求都需要提供用戶(hù)名和密碼。

    相應(yīng)的更新server.js:

    // 引入我們需要的包express var express = require('express'),mongoose = require('mongoose'),bodyParser = require('body-parser'),passport = require('passport'),petController = require('./controllers/pet'),userController = require('./controllers/user'),authController = require('./controllers/auth');// 創(chuàng)建一個(gè)express的server var app = express();app.use(bodyParser.urlencoded({extended: true }));// 連接數(shù)據(jù)庫(kù) mongoose.connect('mongodb://localhost:27017/petshot');...router.route('/pets').post(authController.isAuthenticated, petController.postPets).get(authController.isAuthenticated, petController.getPets);router.route('/pets/:pet_id').get(authController.isAuthenticated, petController.getPet).put(authController.isAuthenticated, petController.updatePet).delete(authController.isAuthenticated, petController.deletePet);// path: /users, for users router.route('/users').post(userController.postUsers).get(authController.isAuthenticated, userController.getUsers);...

    如果還沒(méi)有數(shù)據(jù)的話,首先使用POST方法添加幾個(gè)用戶(hù)。之后GET用戶(hù)測(cè)試一下。如果用戶(hù)名、密碼都對(duì)的話就會(huì)獲得數(shù)據(jù)了。

    使用passport包認(rèn)證還有一個(gè)好處,你可以直接從req獲取user數(shù)據(jù)。如:req.user._id獲得用戶(hù)的_id。有些數(shù)據(jù)需要記錄更新數(shù)據(jù)的用戶(hù),這樣就非常方便了。

    最后

    下文使用更加安全的oauth2認(rèn)證。

    歡迎加群互相學(xué)習(xí),共同進(jìn)步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,轉(zhuǎn)載請(qǐng)注明出處!























    本文轉(zhuǎn)自張昺華-sky博客園博客,原文鏈接:http://www.cnblogs.com/sunshine-anycall/p/5634907.html,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者

    總結(jié)

    以上是生活随笔為你收集整理的基于Node的PetShop,RESTful API以及认证的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 成人中文字幕在线 | 欧美成人综合一区 | 欧美日韩一区二区久久 | 婷婷综合色 | 亚洲免费观看视频 | 久久久久久人妻一区二区三区 | av电影在线观看不卡 | 操干网 | a国产视频| 女人做爰全过程免费观看美女 | 色天天av| 内射后入在线观看一区 | 狠狠操夜夜爽 | 亚洲一区二区三区免费视频 | 99精品亚洲 | 97视频入口 | 九九黄色片 | 欧美精品一卡二卡 | 中国肥胖女人真人毛片 | 久久思| 另类少妇人与禽zozz0性伦 | 四虎黄色影视 | 精品国产乱码久久久久久88av | 精品国产乱码久久久久久闺蜜 | 干美女视频 | 国产91精品一区二区绿帽 | 福利视频第一页 | 凹凸视频一区二区 | 国产精品一区二区在线看 | 97精品人妻一区二区三区 | 激情欧美综合 | 亚洲av无码一区二区三区dv | 福利社区一区二区 | 国产高清成人久久 | 制服丝袜在线一区 | 日一区二区三区 | 97日韩精品| www插插插无码免费视频网站 | 狼人狠狠干 | aaaaa级少妇高潮大片免费看 | 色一情一乱一伦一区二区三区 | www.天天综合| 黄色av网址在线观看 | 麻豆激情网 | 99精品福利视频 | 高清一区二区三区四区 | 午夜激情福利视频 | 九色首页| 中文字幕不卡一区 | 久久大尺度 | 亚洲人掀裙打屁股网站 | 精品人妻一区二区三区日产乱码卜 | 91免费视频黄 | 久久久久亚洲av成人人电影 | 亚洲欧美精品aaaaaa片 | 中文字幕国产在线观看 | 亚洲欧洲久久久 | 在线观看欧美一区二区三区 | 黄站在线观看 | 91极品蜜桃臀 | a在线观看 | 欧美乱子伦 | 99精品黄色 | 欧美日韩亚洲色图 | 欧美在线专区 | 男女激情大尺度做爰视频 | 日韩视频免费在线播放 | 天天干天天操天天干 | 免费看又黄又无码的网站 | 国产真实自拍 | 91av亚洲 | 一区二区在线免费看 | 国产在线观看不卡 | 欧美日韩在线一区 | 成人国产精品入口免费视频 | 亲子伦视频一区二区三区 | 欧美人妻精品一区二区免费看 | 涩涩视频软件 | 国产精品午夜视频 | 日本成人在线免费观看 | 欧美国产一二三区 | 美女黄色在线观看 | 亚洲欧美天堂 | 美国美女群体交乱 | 国产无套内射又大又猛又粗又爽 | a在线观看视频 | av永久免费在线观看 | 成人精品亚洲人成在线 | 国产香蕉精品 | 成人国产视频在线观看 | 狠狠干五月 | 欧日韩在线 | 99久久精品日本一区二区免费 | 夜夜嗨一区二区三区 | 激情久久五月 | 男人用嘴添女人下身免费视频 | 久久久久亚洲色欲AV无码网站 | 国产精品午夜久久 | 日日夜夜噜 |