GraphQL, API'ler için esnek ve verimli bir veri sorgulama ve işleme dili sunan, geleneksel RESTful API mimarisine popüler bir alternatiftir. Onunla benimsenmesi arttıkça, uygulamaları yetkisiz erişimden ve potansiyel verilerden korumak için GraphQL API'lerinin güvenliğine öncelik vermek giderek daha önemli hale geliyor ihlaller.
GraphQL API'lerini güvence altına almak için etkili bir yaklaşım, JSON Web Token'larını (JWT'ler) uygulamaktır. JWT'ler, korunan kaynaklara erişim izni vermek ve yetkili eylemleri gerçekleştirmek için güvenli ve etkili bir yöntem sağlayarak istemciler ve API'ler arasında güvenli iletişim sağlar.
GraphQL API'lerinde Kimlik Doğrulama ve Yetkilendirme
Farklı REST API'leriGraphQL API'leri genellikle müşterilerin sorgularında değişen miktarlarda veriyi dinamik olarak talep etmelerine olanak tanıyan tek bir uç noktaya sahiptir. Bu esneklik onun güçlü yanı olsa da, erişim kontrolü açıklarının bozulması gibi olası güvenlik saldırıları riskini de artırıyor.
Bu riski azaltmak için erişim izinlerinin doğru şekilde tanımlanması da dahil olmak üzere sağlam kimlik doğrulama ve yetkilendirme süreçlerinin uygulanması önemlidir. Bunu yaparak, korunan kaynaklara yalnızca yetkili kullanıcıların erişebileceğini garanti eder ve sonuçta olası güvenlik ihlalleri ve veri kaybı riskini azaltırsınız.
Bu projenin kodunu kendi içinde bulabilirsiniz. GitHub depo.
Express.js Apollo Sunucusu Kurma
Apollo Sunucusu GraphQL API'leri için yaygın olarak kullanılan bir GraphQL sunucu uygulamasıdır. GraphQL şemalarını kolayca oluşturmak, çözümleyicileri tanımlamak ve API'leriniz için farklı veri kaynaklarını yönetmek için bunu kullanabilirsiniz.
Express.js Apollo Sunucusu kurmak için bir proje klasörü oluşturup açın:
mkdir graphql-API-jwt
cd graphql-API-jwt
Daha sonra, yeni bir Node.js projesini başlatmak için bu komutu çalıştırın. npm, Düğüm paket yöneticisi:
npm init --yes
Şimdi bu paketleri kurun.
npm install apollo-server graphql mongoose jsonwebtokens dotenv
Son olarak, bir sunucu.js Dosyayı kök dizine kopyalayın ve sunucunuzu bu kodla kurun:
const { ApolloServer } = require('apollo-server');
const mongoose = require('mongoose');
require('dotenv').config();const typeDefs = require("./graphql/typeDefs");
const resolvers = require("./graphql/resolvers");const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ req }),
});const MONGO_URI = process.env.MONGO_URI;
mongoose
.connect(MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log("Connected to DB");
return server.listen({ port: 5000 });
})
.then((res) => {
console.log(`Server running at ${res.url}`);
})
.catch(err => {
console.log(err.message);
});
GraphQL sunucusu aşağıdakilerle kurulur: typeDefs Ve çözümleyiciler API'nin işleyebileceği şema ve işlemleri belirten parametreler. bağlam seçeneği, req nesnesini her çözümleyicinin bağlamına göre yapılandırır; bu, sunucunun başlık değerleri gibi isteğe özgü ayrıntılara erişmesine olanak tanır.
MongoDB Veritabanı Oluşturma
Veritabanı bağlantısını kurmak için öncelikle MongoDB veritabanı oluştur veya MongoDB Atlas'ta bir küme kurma. Ardından, sağlanan veritabanı bağlantısı URI dizesini kopyalayın, .env dosyasını açın ve bağlantı dizesini aşağıdaki gibi girin:
MONGO_URI=""
Veri Modelini Tanımlayın
Mongoose'u kullanarak bir veri modeli tanımlayın. Yeni bir tane oluştur modeller/user.js dosyalayın ve aşağıdaki kodu ekleyin:
const {model, Schema} = require('mongoose');
const userSchema = new Schema({
name: String,
password: String,
role: String
});
module.exports = model('user', userSchema);
GraphQL Şemasını Tanımlayın
Bir GraphQL API'sinde şema, sorgulanabilecek verilerin yapısını tanımlamanın yanı sıra ana hatlarını da tanımlar. aracılığıyla verilerle etkileşimde bulunmak için gerçekleştirebileceğiniz mevcut işlemler (sorgular ve mutasyonlar) API'dir.
Bir şema tanımlamak için projenizin kök dizininde yeni bir klasör oluşturun ve adını verin. grafikql. Bu klasörün içine iki dosya ekleyin: typeDefs.js Ve çözücüler.js.
İçinde typeDefs.js dosyaya aşağıdaki kodu ekleyin:
const { gql } = require("apollo-server");
const typeDefs = gql`
type User {
id: ID!
name: String!
password: String!
role: String!
}
input UserInput {
name: String!
password: String!
role: String!
}
type TokenResult {
message: String
token: String
}
type Query {
users: [User]
}
type Mutation {
register(userInput: UserInput): User
login(name: String!, password: String!, role: String!): TokenResult
}
`;
module.exports = typeDefs;
GraphQL API için Çözümleyiciler Oluşturun
Çözümleyici işlevler, istemci sorgularına ve mutasyonlara ve ayrıca şemada tanımlanan diğer alanlara yanıt olarak verilerin nasıl alınacağını belirler. Bir istemci bir sorgu veya mutasyon gönderdiğinde GraphQL sunucusu, veritabanları veya API'ler gibi çeşitli kaynaklardan gerekli verileri işlemek ve döndürmek için ilgili çözümleyicileri tetikler.
JSON Web Belirteçlerini (JWT'ler) kullanarak kimlik doğrulama ve yetkilendirme uygulamak için kayıt ve oturum açma mutasyonlarına yönelik çözümleyiciler tanımlayın. Bunlar kullanıcı kaydı ve kimlik doğrulama süreçlerini yönetecektir. Ardından, yalnızca kimliği doğrulanmış ve yetkili kullanıcıların erişebileceği bir veri getirme sorgu çözümleyicisi oluşturun.
Ancak önce JWT'leri oluşturacak ve doğrulayacak işlevleri tanımlayın. İçinde çözücüler.js Dosyaya aşağıdaki içe aktarmaları ekleyerek başlayın.
const User = require("../models/user");
const jwt = require('jsonwebtoken');
const secretKey = process.env.SECRET_KEY;
JSON web tokenlarını imzalamak için kullanacağınız gizli anahtarı .env dosyasına eklediğinizden emin olun.
SECRET_KEY = '' ;
Bir kimlik doğrulama belirteci oluşturmak için, JWT belirteci için benzersiz nitelikleri (ör. son kullanma süresi) de belirten aşağıdaki işlevi ekleyin. Ek olarak, özel uygulama gereksinimlerinize göre zamanında verilenler gibi diğer nitelikleri de dahil edebilirsiniz.
functiongenerateToken(user) {
const token = jwt.sign(
{ id: user.id, role: user.role },
secretKey,
{ expiresIn: '1h', algorithm: 'HS256' }
);
return token;
}
Şimdi, sonraki HTTP isteklerinde yer alan JWT belirteçlerini doğrulamak için belirteç doğrulama mantığını uygulayın.
functionverifyToken(token) {
if (!token) {
thrownewError('Token not provided');
}
try {
const decoded = jwt.verify(token, secretKey, { algorithms: ['HS256'] });
return decoded;
} catch (err) {
thrownewError('Invalid token');
}
}
Bu işlev, giriş olarak bir jeton alır, belirtilen gizli anahtarı kullanarak geçerliliğini doğrular ve geçerliyse kodu çözülmüş jetonu döndürür, aksi takdirde geçersiz bir jetonu belirten bir hata atar.
API Çözümleyicilerini Tanımlayın
GraphQL API'sine yönelik çözümleyicileri tanımlamak için yöneteceği belirli işlemleri, bu durumda kullanıcı kaydı ve oturum açma işlemlerini özetlemeniz gerekir. Öncelikle bir tane oluşturun çözümleyiciler çözümleyici işlevlerini tutacak nesneyi seçin ve ardından aşağıdaki mutasyon işlemlerini tanımlayın:
const resolvers = {
Mutation: {
register: async (_, { userInput: { name, password, role } }) => {
if (!name || !password || !role) {
thrownewError('Name password, and role required');
}const newUser = new User({
name: name,
password: password,
role: role,
});try {
const response = await newUser.save();return {
id: response._id,
...response._doc,
};
} catch (error) {
console.error(error);
thrownewError('Failed to create user');
}
},
login: async (_, { name, password }) => {
try {
const user = await User.findOne({ name: name });if (!user) {
thrownewError('User not found');
}if (password !== user.password) {
thrownewError('Incorrect password');
}const token = generateToken(user);
if (!token) {
thrownewError('Failed to generate token');
}
return {
message: 'Login successful',
token: token,
};
} catch (error) {
console.error(error);
thrownewError('Login failed');
}
}
},
kayıt olmak mutasyon, yeni kullanıcı verilerini veritabanına ekleyerek kayıt işlemini gerçekleştirir. iken giriş yapmak mutasyon, kullanıcı oturum açma işlemlerini yönetir; başarılı bir kimlik doğrulama durumunda, bir JWT belirteci oluşturacak ve yanıtta bir başarı mesajı döndürecektir.
Şimdi kullanıcı verilerini almak için sorgu çözümleyiciyi ekleyin. Bu sorgunun yalnızca kimliği doğrulanmış ve yetkili kullanıcılar tarafından erişilebilir olmasını sağlamak amacıyla, erişimi yalnızca sorguya sahip kullanıcılarla sınırlandıracak yetkilendirme mantığını ekleyin. Yönetici rol.
Temel olarak sorgu önce belirtecin geçerliliğini, ardından kullanıcı rolünü kontrol edecektir. Yetkilendirme kontrolü başarılı olursa, çözümleyici sorgusu kullanıcıların verilerini veritabanından alıp döndürmeye devam edecektir.
Query: {
users: async (parent, args, context) => {
try {
const token = context.req.headers.authorization || '';
const decodedToken = verifyToken(token);if (decodedToken.role !== 'Admin') {
thrownew ('Unauthorized. Only Admins can access this data.');
}
const users = await User.find({}, { name: 1, _id: 1, role:1 });
return users;
} catch (error) {
console.error(error);
thrownewError('Failed to fetch users');
}
},
},
};
Son olarak geliştirme sunucusunu başlatın:
node server.js
Mükemmel! Şimdi devam edin ve tarayıcınızdaki Apollo Sunucu API sanal alanını kullanarak API'nin işlevselliğini test edin. Örneğin, şunları kullanabilirsiniz: kayıt olmak veritabanına yeni kullanıcı verileri eklemek için mutasyon ve ardından giriş yapmak Kullanıcının kimliğini doğrulamak için mutasyon.
Son olarak, JWT belirtecini yetkilendirme başlığı bölümüne ekleyin ve kullanıcı verileri için veritabanını sorgulamaya devam edin.
GraphQL API'lerinin güvenliğini sağlama
Kimlik doğrulama ve yetkilendirme, GraphQL API'lerinin güvenliğini sağlamak için çok önemli bileşenlerdir. Bununla birlikte, kapsamlı güvenliği sağlamak için bunların tek başına yeterli olmayabileceğini kabul etmek önemlidir. Giriş doğrulama ve hassas verilerin şifrelenmesi gibi ek güvenlik önlemlerini uygulamanız gerekir.
Kapsamlı bir güvenlik yaklaşımı benimseyerek API'lerinizi farklı potansiyel saldırılara karşı koruyabilirsiniz.