Node.js'de Güvenli REST API Oluşturma

Yayınlanan: 2022-03-11

Uygulama programlama arabirimleri (API'ler) her yerdedir. Yazılımın diğer yazılım parçalarıyla (dahili veya harici) tutarlı bir şekilde iletişim kurmasını sağlarlar; bu, yeniden kullanılabilirlikten bahsetmeye gerek bile yok, ölçeklenebilirliğin önemli bir bileşenidir.

Günümüzde çevrimiçi hizmetlerin halka açık API'lere sahip olması oldukça yaygındır. Bunlar, diğer geliştiricilerin sosyal medya girişleri, kredi kartı ödemeleri ve davranış izleme gibi özellikleri kolayca entegre etmelerini sağlar. Bunun için kullandıkları fiili standarda Temsili Durum Transferi (REST) ​​denir.

ASP.NET Core, Laravel (PHP) veya Bottle (Python) gibi görev için çok sayıda platform ve programlama dili kullanılabilirken, bu eğitimde, kullanarak basit ama güvenli bir REST API arka ucu oluşturacağız. aşağıdaki yığın:

  • Okuyucunun zaten aşina olması gereken Node.js
  • Node.js altında ortak web sunucusu görevlerini oluşturmayı büyük ölçüde basitleştiren ve bir REST API arka ucu oluşturmanın standart ücreti olan Express
  • Arka ucumuzu bir MongoDB veritabanına bağlayacak olan Mongoose

Bu öğreticiyi takip eden geliştiriciler, terminal (veya komut istemi) konusunda da rahat olmalıdır.

Not: Burada bir ön uç kod tabanını ele almayacağız, ancak arka uçumuzun JavaScript ile yazılmış olması, kodun (örneğin nesne modellerinin) tüm yığın boyunca paylaşılmasını kolaylaştırır.

Bir REST API'sinin Anatomisi

REST API'leri, ortak bir durum bilgisi olmayan işlemler kümesini kullanarak verilere erişmek ve bunları değiştirmek için kullanılır. Bu işlemler HTTP protokolünün ayrılmaz bir parçasıdır ve bire bir temiz olmasa da temel oluşturma, okuma, güncelleme ve silme (CRUD) işlevselliğini temsil eder:

  • POST (bir kaynak oluşturun veya genel olarak veri sağlayın)
  • GET (bir kaynak dizini veya tek bir kaynak alın)
  • PUT (bir kaynak oluşturun veya değiştirin)
  • PATCH (bir kaynağı güncelleme/değiştirme)
  • DELETE (bir kaynağı kaldır)

Bu HTTP işlemlerini ve bir kaynak adını adres olarak kullanarak, her işlem için bir uç nokta oluşturarak bir REST API oluşturabiliriz. Ve kalıbı uygulayarak, kodu hızlı bir şekilde geliştirmemizi ve daha sonra sürdürmemizi sağlayan istikrarlı ve kolay anlaşılır bir temele sahip olacağız. Daha önce belirtildiği gibi, aynı temel, çoğu aynı şekilde REST API'lerini kullanan üçüncü taraf özelliklerini entegre etmek için kullanılacak ve bu entegrasyon daha hızlı hale gelecektir.

Şimdilik, Node.js kullanarak güvenli REST API'mizi oluşturmaya başlayalım!

Bu öğreticide, users adlı bir kaynak için oldukça yaygın (ve çok pratik) bir REST API oluşturacağız.

Kaynağımız aşağıdaki temel yapıya sahip olacaktır:

  • id (otomatik olarak oluşturulmuş bir UUID)
  • firstName
  • lastName
  • email
  • password
  • permissionLevel (bu kullanıcının ne yapmasına izin verilir?)

Ve bu kaynak için aşağıdaki işlemleri oluşturacağız:

  • /users uç noktasında POST (yeni bir kullanıcı oluşturun)
  • /users uç noktasında GET (tüm kullanıcıları listeleyin)
  • /users/:userId uç noktasında GET (belirli bir kullanıcı alın)
  • /users/:userId uç noktasındaki PATCH (belirli bir kullanıcı için verileri güncelleyin)
  • /users/:userId uç noktasında DELETE (belirli bir kullanıcıyı kaldırın)

Ayrıca erişim belirteçleri için JSON web belirteçlerini (JWT'ler) kullanacağız. Bu amaçla, bir kullanıcının e-postasını ve parolasını bekleyecek ve karşılığında belirli işlemlerde kimlik doğrulama için kullanılan belirteci oluşturacak olan auth adlı başka bir kaynak oluşturacağız. (Dejan Miloseviç'in Java'da güvenli REST uygulamaları için JWT hakkındaki harika makalesi bu konuda daha fazla ayrıntıya giriyor; ilkeler aynı.)

REST API Eğitimi Kurulumu

Her şeyden önce, en son Node.js sürümünün kurulu olduğundan emin olun. Bu makale için 14.9.0 sürümünü kullanacağım; eski sürümlerde de çalışabilir.

Ardından, MongoDB'nin kurulu olduğundan emin olun. Burada kullanılan Mongoose ve MongoDB'nin özelliklerini açıklamayacağız, ancak temelleri çalıştırmak için sunucuyu bir hizmet olarak değil, etkileşimli modda (yani, mongo olarak komut satırından) başlatmanız yeterlidir. Bunun nedeni, bu öğreticinin bir noktasında, Node.js kodumuz yerine doğrudan MongoDB ile etkileşim kurmamız gerekecek.

Not: MongoDB ile, bazı RDBMS senaryolarında olabileceği gibi belirli bir veritabanı oluşturmaya gerek yoktur. Node.js kodumuzdan ilk ekleme çağrısı, oluşturulmasını otomatik olarak tetikleyecektir.

Bu öğretici, çalışan bir proje için gerekli olan tüm kodu içermez. Bunun yerine, tamamlayıcı depoyu klonlamanız ve okurken öne çıkanları takip etmeniz amaçlanmıştır - ancak isterseniz, gerektiğinde depodan belirli dosyalara ve parçacıklara da kopyalayabilirsiniz.

Terminalinizde ortaya çıkan rest-api-tutorial/ klasörüne gidin. Projemizin üç modül klasörü içerdiğini göreceksiniz:

  • common (tüm paylaşılan hizmetleri ve kullanıcı modülleri arasında paylaşılan bilgileri işleme)
  • users (kullanıcılarla ilgili her şey)
  • auth (JWT oluşturma ve oturum açma akışını yönetme)

Şimdi, npm install çalıştırın (veya varsa, yarn çalıştırın.)

Tebrikler, artık basit REST API arka uçumuzu çalıştırmak için gereken tüm bağımlılıklara ve kuruluma sahipsiniz.

Kullanıcı Modülü Oluşturma

Kullanıcı şeması içinde kullanıcı modelini oluşturmak için MongoDB için bir nesne veri modelleme (ODM) kitaplığı olan Mongoose'u kullanacağız.

İlk olarak, /users/models/users.model.js içinde Mongoose şemasını oluşturmamız gerekiyor:

 const userSchema = new Schema({ firstName: String, lastName: String, email: String, password: String, permissionLevel: Number });

Şemayı tanımladıktan sonra şemayı kullanıcı modeline kolayca ekleyebiliriz.

 const userModel = mongoose.model('Users', userSchema);

Bundan sonra, Express uç noktalarımız içinde istediğimiz tüm CRUD işlemlerini uygulamak için bu modeli kullanabiliriz.

users/routes.config.js içinde rotayı tanımlayarak “kullanıcı oluştur” işlemine başlayalım:

 app.post('/users', [ UsersController.insert ]);

Bu, ana index.js dosyasındaki Express uygulamamıza çekilir. UsersController nesnesi, /users/controllers/users.controller.js içinde tanımlanan parolayı uygun şekilde hash ettiğimiz denetleyicimizden içe aktarılır:

 exports.insert = (req, res) => { let salt = crypto.randomBytes(16).toString('base64'); let hash = crypto.createHmac('sha512',salt) .update(req.body.password) .digest("base64"); req.body.password = salt + "$" + hash; req.body.permissionLevel = 1; UserModel.createUser(req.body) .then((result) => { res.status(201).send({id: result._id}); }); };

Bu noktada, sunucuyu çalıştırarak ( npm start ) ve /users users'a bazı JSON verileriyle bir POST isteği göndererek Mongoose modelimizi test edebiliriz:

 { "firstName" : "Marcos", "lastName" : "Silva", "email" : "[email protected]", "password" : "s3cr3tp4sswo4rd" }

Bunun için kullanabileceğiniz birkaç araç var. Insomnia (aşağıda ele alınmıştır) ve Postman, popüler GUI araçlarıdır ve curl , yaygın bir CLI seçimidir. Hatta örneğin tarayıcınızın yerleşik geliştirme araçları konsolundan JavaScript'i de kullanabilirsiniz:

 fetch('http://localhost:3600/users', { method: 'POST', headers: { "Content-type": "application/json" }, body: JSON.stringify({ "firstName": "Marcos", "lastName": "Silva", "email": "[email protected]", "password": "s3cr3tp4sswo4rd" }) }) .then(function(response) { return response.json(); }) .then(function(data) { console.log('Request succeeded with JSON response', data); }) .catch(function(error) { console.log('Request failed', error); });

Bu noktada, geçerli bir gönderinin sonucu yalnızca oluşturulan kullanıcının kimliği olacaktır: { "id": "5b02c5c84817bf28049e58a3" } . Ayrıca users/models/users.model.js içindeki modele createUser yöntemini eklememiz gerekiyor:

 exports.createUser = (userData) => { const user = new User(userData); return user.save(); };

Her şey hazır, şimdi kullanıcının var olup olmadığını görmemiz gerekiyor. Bunun için şu uç nokta için “kullanıcıyı kimliğe göre al” özelliğini uygulayacağız: users/:userId .

İlk olarak, /users/routes/config.js içinde bir rota oluşturuyoruz:

 app.get('/users/:userId', [ UsersController.getById ]);

Ardından, denetleyiciyi /users/controllers/users.controller.js içinde oluşturuyoruz:

 exports.getById = (req, res) => { UserModel.findById(req.params.userId).then((result) => { res.status(200).send(result); }); };

Son olarak, /users/models/users.model.js içindeki modele findById yöntemini /users/models/users.model.js :

 exports.findById = (id) => { return User.findById(id).then((result) => { result = result.toJSON(); delete result._id; delete result.__v; return result; }); };

Cevap şu şekilde olacaktır:

 { "firstName": "Marcos", "lastName": "Silva", "email": "[email protected]", "password": "Y+XZEaR7J8xAQCc37nf1rw==$p8b5ykUx6xpC6k8MryDaRmXDxncLumU9mEVabyLdpotO66Qjh0igVOVerdqAh+CUQ4n/E0z48mp8SDTpX2ivuQ==", "permissionLevel": 1, "id": "5b02c5c84817bf28049e58a3" }

Karma şifreyi görebileceğimizi unutmayın. Bu öğretici için parolayı gösteriyoruz, ancak en bariz en iyi uygulama, hash uygulanmış olsa bile parolayı asla açıklamamaktır. Görebildiğimiz diğer bir şey ise daha sonra kullanıcı permissionLevel işlemek için kullanacağımız allowLevel .

Yukarıda belirtilen kalıbı tekrarlayarak, artık kullanıcıyı güncelleme işlevini ekleyebiliriz. Sadece değiştirmek istediğimiz alanları göndermemizi sağlayacağı için PATCH işlemini kullanacağız. Bu nedenle rota, /users/:userid için PATCH olacaktır ve değiştirmek istediğimiz tüm alanları göndereceğiz. Değişikliklerin söz konusu kullanıcıyla veya bir yöneticiyle sınırlandırılması gerektiğinden ve yalnızca bir yönetici permissionLevel değerini değiştirebileceğinden, bazı ekstra doğrulamalar uygulamamız gerekecek. Şimdilik bunu atlayacağız ve auth modülünü uyguladığımızda buna geri döneceğiz. Şimdilik denetleyicimiz şöyle görünecek:

 exports.patchById = (req, res) => { if (req.body.password){ let salt = crypto.randomBytes(16).toString('base64'); let hash = crypto.createHmac('sha512', salt).update(req.body.password).digest("base64"); req.body.password = salt + "$" + hash; } UserModel.patchUser(req.params.userId, req.body).then((result) => { res.status(204).send({}); }); };

Varsayılan olarak, isteğin başarılı olduğunu belirtmek için yanıt gövdesi olmayan bir HTTP kodu 204 göndereceğiz.

Ve modele patchUser yöntemini eklememiz gerekecek:

 exports.patchUser = (id, userData) => { return User.findOneAndUpdate({ _id: id }, userData); };

Kullanıcı listesi, aşağıdaki denetleyici tarafından /users/ konumunda bir GET olarak uygulanacaktır:

 exports.list = (req, res) => { let limit = req.query.limit && req.query.limit <= 100 ? parseInt(req.query.limit) : 10; let page = 0; if (req.query) { if (req.query.page) { req.query.page = parseInt(req.query.page); page = Number.isInteger(req.query.page) ? req.query.page : 0; } } UserModel.list(limit, page).then((result) => { res.status(200).send(result); }) };

İlgili model yöntemi şöyle olacaktır:

 exports.list = (perPage, page) => { return new Promise((resolve, reject) => { User.find() .limit(perPage) .skip(perPage * page) .exec(function (err, users) { if (err) { reject(err); } else { resolve(users); } }) }); };

Ortaya çıkan liste yanıtı aşağıdaki yapıya sahip olacaktır:

 [ { "firstName": "Marco", "lastName": "Silva", "email": "[email protected]", "password": "z4tS/DtiH+0Gb4J6QN1K3w==$al6sGxKBKqxRQkDmhnhQpEB6+DQgDRH2qr47BZcqLm4/fphZ7+a9U+HhxsNaSnGB2l05Oem/BLIOkbtOuw1tXA==", "permissionLevel": 1, "id": "5b02c5c84817bf28049e58a3" }, { "firstName": "Paulo", "lastName": "Silva", "email": "[email protected]", "password": "wTsqO1kHuVisfDIcgl5YmQ==$cw7RntNrNBNw3MO2qLbx959xDvvrDu4xjpYfYgYMxRVDcxUUEgulTlNSBJjiDtJ1C85YimkMlYruU59rx2zbCw==", "permissionLevel": 1, "id": "5b02d038b653603d1ca69729" } ]

Ve uygulanacak son kısım, /users/:userId DELETE

Silme denetleyicimiz şöyle olacaktır:

 exports.removeById = (req, res) => { UserModel.removeById(req.params.userId) .then((result)=>{ res.status(204).send({}); }); };

Daha önce olduğu gibi, denetleyici, onay olarak HTTP kodu 204 ve içerik gövdesi döndürmez.

İlgili model yöntemi şöyle görünmelidir:

 exports.removeById = (userId) => { return new Promise((resolve, reject) => { User.deleteMany({_id: userId}, (err) => { if (err) { reject(err); } else { resolve(err); } }); }); };

Artık kullanıcı kaynağını işlemek için gerekli tüm işlemlere sahibiz ve kullanıcı denetleyicisiyle işimiz bitti. Bu kodun ana fikri, size REST modelini kullanmanın temel kavramlarını vermektir. Bazı doğrulamaları ve izinleri uygulamak için bu koda geri dönmemiz gerekecek, ancak önce güvenliğimizi oluşturmaya başlamamız gerekecek. Auth modülünü oluşturalım.

Yetkilendirme Modülü Oluşturma

İzin ve doğrulama ara katman yazılımını uygulayarak users modülünün güvenliğini sağlamadan önce, mevcut kullanıcı için geçerli bir belirteç oluşturabilmemiz gerekir. Geçerli bir e-posta ve şifre sağlayan kullanıcıya yanıt olarak bir JWT oluşturacağız. JWT, kullanıcının tekrar tekrar doğrulama yapmadan güvenli bir şekilde birkaç istekte bulunmasını sağlamak için kullanabileceğiniz dikkate değer bir JSON web belirtecidir. Genellikle bir sona erme süresi vardır ve iletişimi güvende tutmak için birkaç dakikada bir yeni bir belirteç yeniden oluşturulur. Ancak bu eğitim için, belirteci yenilemekten vazgeçeceğiz ve oturum başına tek bir belirteçle basit tutacağız.

İlk olarak, /auth kaynağına yapılan POST istekleri için bir uç nokta oluşturacağız. İstek gövdesi, kullanıcı e-postasını ve şifresini içerecektir:

 { "email" : "[email protected]", "password" : "s3cr3tp4sswo4rd2" }

Denetleyiciyi devreye sokmadan önce, /authorization/middlewares/verify.user.middleware.js içindeki kullanıcıyı doğrulamalıyız:

 exports.isPasswordAndUserMatch = (req, res, next) => { UserModel.findByEmail(req.body.email) .then((user)=>{ if(!user[0]){ res.status(404).send({}); }else{ let passwordFields = user[0].password.split('$'); let salt = passwordFields[0]; let hash = crypto.createHmac('sha512', salt).update(req.body.password).digest("base64"); if (hash === passwordFields[1]) { req.body = { userId: user[0]._id, email: user[0].email, permissionLevel: user[0].permissionLevel, provider: 'email', name: user[0].firstName + ' ' + user[0].lastName, }; return next(); } else { return res.status(400).send({errors: ['Invalid email or password']}); } } }); };

Bunu yaptıktan sonra kontrolöre geçebilir ve JWT'yi oluşturabiliriz:

 exports.login = (req, res) => { try { let refreshId = req.body.userId + jwtSecret; let salt = crypto.randomBytes(16).toString('base64'); let hash = crypto.createHmac('sha512', salt).update(refreshId).digest("base64"); req.body.refreshKey = salt; let token = jwt.sign(req.body, jwtSecret); let b = Buffer.from(hash); let refresh_token = b.toString('base64'); res.status(201).send({accessToken: token, refreshToken: refresh_token}); } catch (err) { res.status(500).send({errors: err}); } };

Bu öğreticide belirteci yenilemeyecek olsak da, denetleyici, sonraki geliştirmede uygulamayı kolaylaştırmak için bu tür bir nesli etkinleştirecek şekilde ayarlanmıştır.

Şimdi tek ihtiyacımız olan rotayı oluşturmak ve /authorization/routes.config.js içinde uygun ara yazılımı çağırmak:

 app.post('/auth', [ VerifyUserMiddleware.hasAuthValidFields, VerifyUserMiddleware.isPasswordAndUserMatch, AuthorizationController.login ]);

Yanıt, accessToken alanında oluşturulan JWT'yi içerecektir:

 { "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1YjAyYzVjODQ4MTdiZjI4MDQ5ZTU4YTMiLCJlbWFpbCI6Im1hcmNvcy5oZW5yaXF1ZUB0b3B0YWwuY29tIiwicGVybWlzc2lvbkxldmVsIjoxLCJwcm92aWRlciI6ImVtYWlsIiwibmFtZSI6Ik1hcmNvIFNpbHZhIiwicmVmcmVzaF9rZXkiOiJiclhZUHFsbUlBcE1PakZIRG1FeENRPT0iLCJpYXQiOjE1MjY5MjMzMDl9.mmNg-i44VQlUEWP3YIAYXVO-74803v1mu-y9QPUQ5VY", "refreshToken": "U3BDQXBWS3kyaHNDaGJNanlJTlFkSXhLMmFHMzA2NzRsUy9Sd2J0YVNDTmUva0pIQ0NwbTJqOU5YZHgxeE12NXVlOUhnMzBWMGNyWmdOTUhSaTdyOGc9PQ==" }

Belirteci oluşturduktan sonra, onu Authorization başlığının içinde Bearer ACCESS_TOKEN formunu kullanarak kullanabiliriz.

İzinler ve Doğrulamalar Ara Yazılımı Oluşturma

Tanımlamamız gereken ilk şey, users kaynağını kimin kullanabileceğidir. Bunlar, ele almamız gereken senaryolardır:

  • Kullanıcı oluşturmak için herkese açık (kayıt işlemi). Bu senaryo için JWT kullanmayacağız.
  • Oturum açmış kullanıcı ve yöneticilerin bu kullanıcıyı güncellemesi için özel.
  • Yönetici için özel, yalnızca kullanıcı hesaplarını kaldırmak için.

Bu senaryoları belirledikten sonra, öncelikle, kullanıcı geçerli bir JWT kullanıyorsa her zaman doğrulayan bir ara katman yazılımına ihtiyaç duyacağız. /common/middlewares/auth.validation.middleware.js içindeki ara katman yazılımı şu kadar basit olabilir:

 exports.validJWTNeeded = (req, res, next) => { if (req.headers['authorization']) { try { let authorization = req.headers['authorization'].split(' '); if (authorization[0] !== 'Bearer') { return res.status(401).send(); } else { req.jwt = jwt.verify(authorization[1], secret); return next(); } } catch (err) { return res.status(403).send(); } } else { return res.status(401).send(); } };

İstek hatalarını işlemek için HTTP hata kodlarını kullanacağız:

  • Geçersiz bir istek için HTTP 401
  • Geçersiz belirteçli geçerli bir istek veya geçersiz izinlere sahip geçerli belirteç için HTTP 403

İzinleri kontrol etmek için bitsel AND operatörünü (bit maskeleme) kullanabiliriz. Her bir gerekli izni 2'nin gücü olarak ayarlarsak, 32 bit tamsayının her bitini tek bir izin olarak değerlendirebiliriz. Daha sonra bir yönetici, izin değerini 2147483647 olarak ayarlayarak tüm izinlere sahip olabilir. Bu kullanıcının daha sonra herhangi bir rotaya erişimi olabilir. Başka bir örnek olarak, izin değeri 7 olarak ayarlanmış bir kullanıcı, 1, 2 ve 4 (iki üzeri 0, 1 ve 2 kuvveti) değerleri için bitlerle işaretlenmiş roller için izinlere sahip olacaktır.

Bunun için ara katman yazılımı şöyle görünür:

 exports.minimumPermissionLevelRequired = (required_permission_level) => { return (req, res, next) => { let user_permission_level = parseInt(req.jwt.permission_level); let user_id = req.jwt.user_id; if (user_permission_level & required_permission_level) { return next(); } else { return res.status(403).send(); } }; };

Ara katman yazılımı geneldir. Kullanıcı izin seviyesi ile gerekli izin seviyesi en az bir bitte çakışırsa sonuç sıfırdan büyük olur ve işlemin devam etmesine izin verebiliriz; aksi takdirde, HTTP kodu 403 döndürülür.

Şimdi, /users/routes.config.js içindeki kullanıcının modül yollarına kimlik doğrulama ara yazılımını eklememiz gerekiyor:

 app.post('/users', [ UsersController.insert ]); app.get('/users', [ ValidationMiddleware.validJWTNeeded, PermissionMiddleware.minimumPermissionLevelRequired(PAID), UsersController.list ]); app.get('/users/:userId', [ ValidationMiddleware.validJWTNeeded, PermissionMiddleware.minimumPermissionLevelRequired(FREE), PermissionMiddleware.onlySameUserOrAdminCanDoThisAction, UsersController.getById ]); app.patch('/users/:userId', [ ValidationMiddleware.validJWTNeeded, PermissionMiddleware.minimumPermissionLevelRequired(FREE), PermissionMiddleware.onlySameUserOrAdminCanDoThisAction, UsersController.patchById ]); app.delete('/users/:userId', [ ValidationMiddleware.validJWTNeeded, PermissionMiddleware.minimumPermissionLevelRequired(ADMIN), UsersController.removeById ]);

Bu, REST API'mizin temel geliştirmesini tamamlar. Yapılması gereken tek şey hepsini test etmek.

Uykusuzlukla Koşma ve Test Etme

Insomnia, iyi bir ücretsiz sürümü olan iyi bir REST istemcisidir. En iyi uygulama, elbette, projeye kod testleri eklemek ve uygun hata raporlamasını uygulamaktır, ancak üçüncü taraf REST istemcileri, hata raporlama ve hizmette hata ayıklama mevcut olmadığında üçüncü taraf çözümlerini test etmek ve uygulamak için mükemmeldir. Bir uygulamanın rolünü oynamak ve API'mizde neler olup bittiğine dair bir fikir edinmek için burada kullanacağız.

Bir kullanıcı oluşturmak için, gerekli alanları uygun uç noktaya POST yapmamız ve oluşturulan kimliği sonraki kullanım için saklamamız yeterlidir.

Kullanıcı oluşturmak için uygun verilerle istek

API, kullanıcı kimliğiyle yanıt verecektir:

Kullanıcı kimliği ile onay yanıtı

Artık /auth/ bitiş noktasını kullanarak JWT'yi oluşturabiliriz:

Giriş verileriyle istek

Yanıtımız olarak bir jeton almalıyız:

İlgili JSON Web Simgesini içeren onay

accessToken alın, Bearer ile önek ekleyin (boşluğu unutmayın) ve Authorization altındaki istek başlıklarına ekleyin:

Aktarmak için başlıkların ayarlanması, kimlik doğrulaması yapan JWT'yi içerir

İzinler ara katman yazılımını uyguladığımıza göre bunu şimdi yapmazsak, kayıt dışındaki her istek HTTP kodu 401'i döndürür. Geçerli belirteç yerindeyken, /users/:userId aşağıdaki yanıtı alırız:

Belirtilen kullanıcı için verileri listeleyen yanıt

Ayrıca, daha önce de belirtildiği gibi, eğitim amaçlı ve basitlik adına tüm alanları sergiliyoruz. Parola (karma veya başka türlü) yanıtta hiçbir zaman görünmemelidir.

Kullanıcıların bir listesini almaya çalışalım:

Tüm kullanıcıların bir listesini isteyin

Sürpriz! 403 yanıtı alıyoruz.

Uygun izin seviyesinin olmaması nedeniyle işlem reddedildi

Kullanıcımızın bu uç noktaya erişim izni yok. Kullanıcımızın permissionLevel seviyesini 1'den 7'ye değiştirmemiz gerekecek (hatta ücretsiz ve ücretli izin seviyelerimiz sırasıyla 1 ve 4 olarak temsil edildiğinden 5 bile yapardı.) Bunu MongoDB'de interaktif komut isteminde manuel olarak yapabiliriz. , bunun gibi (kimlik yerel sonucunuzla değiştirildi):

 db.users.update({"_id" : ObjectId("5b02c5c84817bf28049e58a3")},{$set:{"permissionLevel":5}})

Ardından, yeni bir JWT oluşturmamız gerekiyor.

Bu yapıldıktan sonra uygun yanıtı alırız:

Tüm kullanıcılar ve verileriyle yanıt verin

Ardından, /users/:userId uç noktamıza bazı alanlarla birlikte bir PATCH isteği göndererek güncelleme işlevini test edelim:

Güncellenecek kısmi veri içeren istek

Başarılı bir işlemin teyidi olarak 204 yanıtı bekliyoruz, ancak kullanıcıdan bir kez daha doğrulamasını isteyebiliriz.

Başarılı değişiklikten sonra yanıt

Son olarak, kullanıcıyı silmemiz gerekiyor. Yukarıda açıklandığı gibi yeni bir kullanıcı oluşturmamız gerekecek (kullanıcı kimliğini not etmeyi unutmayın) ve bir yönetici kullanıcı için uygun JWT'ye sahip olduğumuzdan emin olun. Yeni kullanıcının, silme işlemini de gerçekleştirebilmesi için izinlerinin 2053'e (bu 2048— ADMIN — artı önceki 5) ayarlanmış olması gerekir. Bu yapıldıktan ve yeni bir JWT oluşturulduktan sonra, Authorization isteği başlığımızı güncellememiz gerekecek:

Bir kullanıcıyı silmek için kurulum iste

/users/:userId bir DELETE isteği gönderirken, onay olarak 204 yanıtı almalıyız. /users/ 'dan mevcut tüm kullanıcıları listelemesini isteyerek tekrar doğrulayabiliriz.

REST API'niz için Sonraki Adımlar

Bu öğreticide ele alınan araçlar ve yöntemlerle artık Node.js üzerinde basit ve güvenli REST API'leri oluşturabilirsiniz. Süreç için gerekli olmayan birçok en iyi uygulama atlandı, bu nedenle şunları unutmayın:

  • Uygun doğrulamaları uygulayın (örneğin, kullanıcı e-postasının benzersiz olduğundan emin olun)
  • Birim testi ve hata raporlaması uygulayın
  • Kullanıcıların kendi izin düzeylerini değiştirmelerini önleyin
  • Yöneticilerin kendilerini kaldırmasını önleme
  • Hassas bilgilerin ifşa edilmesini önleyin (ör. karma parolalar)
  • JWT sırrını common/config/env.config.js depo dışı, çevre tabanlı olmayan bir gizli dağıtım mekanizmasına taşıyın

Okuyucu için son bir alıştırma, kod tabanını JavaScript vaatlerinin kullanımından async/await tekniğine dönüştürmek olabilir.

İlgilenebilecekleriniz için, artık projenin bir TypeScript sürümü de mevcut.

İlgili: REST Spesifikasyonu ile Hiç Yapmadığınız 5 Şey