GraphQL je populárna alternatíva k tradičnej RESTful API architektúre, ktorá ponúka flexibilný a efektívny dátový dotazovací a manipulačný jazyk pre API. S tým s rastúcim prijatím sa stáva čoraz dôležitejším uprednostňovať bezpečnosť GraphQL API na ochranu aplikácií pred neoprávneným prístupom a potenciálnymi údajmi. porušenia.

Jedným z účinných prístupov na zabezpečenie rozhraní API GraphQL je implementácia webových tokenov JSON (JWT). JWT poskytujú bezpečnú a efektívnu metódu udeľovania prístupu k chráneným zdrojom a vykonávania autorizovaných akcií, čím zabezpečujú bezpečnú komunikáciu medzi klientmi a API.

Autentifikácia a autorizácia v GraphQL API

Na rozdiel od REST APIRozhrania API GraphQL majú zvyčajne jeden koncový bod, ktorý umožňuje klientom dynamicky požadovať rôzne množstvá údajov vo svojich dotazoch. Aj keď je táto flexibilita jej silnou stránkou, zvyšuje aj riziko potenciálnych bezpečnostných útokov, ako sú napríklad zraniteľné miesta v oblasti kontroly prístupu.

Na zmiernenie tohto rizika je dôležité implementovať robustné procesy autentifikácie a autorizácie vrátane správneho definovania prístupových oprávnení. Tým zaručíte, že k chráneným zdrojom budú mať prístup iba autorizovaní používatelia, a v konečnom dôsledku znížite riziko potenciálneho narušenia bezpečnosti a straty údajov.

instagram viewer

Kód tohto projektu nájdete v ňom GitHub Úložisko.

Nastavte Express.js Apollo Server

Server Apollo je široko používaná implementácia servera GraphQL pre rozhrania GraphQL API. Môžete ho použiť na jednoduché vytváranie schém GraphQL, definovanie resolverov a správu rôznych zdrojov údajov pre vaše API.

Ak chcete nastaviť Express.js Apollo Server, vytvorte a otvorte priečinok projektu:

mkdir graphql-API-jwt
cd graphql-API-jwt

Potom spustite tento príkaz na inicializáciu nového projektu Node.js pomocou npm, správca balíkov Node:

npm init --yes

Teraz nainštalujte tieto balíčky.

npm install apollo-server graphql mongoose jsonwebtokens dotenv

Nakoniec vytvorte a server.js súbor v koreňovom adresári a nastavte svoj server pomocou tohto kódu:

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);
});

Server GraphQL je nastavený s typeDefs a riešiteľov parametre, špecifikujúce schému a operácie, ktoré API dokáže spracovať. The kontext voľba nakonfiguruje objekt req do kontextu každého resolvera, čo umožní serveru prístup k detailom špecifickým pre požiadavku, ako sú hodnoty hlavičky.

Vytvorte databázu MongoDB

Najprv vytvorte pripojenie k databáze vytvorte databázu MongoDB alebo nastaviť klaster na MongoDB Atlas. Potom skopírujte poskytnutý reťazec URI pripojenia k databáze, vytvorte a .env súbor a zadajte reťazec pripojenia takto:

MONGO_URI=""

Definujte dátový model

Definujte dátový model pomocou Mongoose. Vytvorte nový models/user.js súbor a zahrňte nasledujúci kód:

const {model, Schema} = require('mongoose');

const userSchema = new Schema({
name: String,
password: String,
role: String
});

module.exports = model('user', userSchema);

Definujte schému GraphQL

V rozhraní GraphQL API schéma definuje štruktúru údajov, na ktoré možno dotazovať, ako aj načrtnutie dostupné operácie (dotazy a mutácie), ktoré môžete vykonať na interakciu s údajmi prostredníctvom API.

Ak chcete definovať schému, vytvorte nový priečinok v koreňovom adresári vášho projektu a pomenujte ho graphql. Do tohto priečinka pridajte dva súbory: typeDefs.js a resolvers.js.

V typeDefs.js súbor, zahrňte nasledujúci kód:

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;

Vytvorte Resolvery pre GraphQL API

Funkcie analyzátora určujú, ako sa získavajú údaje ako odpoveď na klientske dotazy a mutácie, ako aj ďalšie polia definované v schéme. Keď klient odošle dotaz alebo mutáciu, server GraphQL spustí príslušné prekladače na spracovanie a vrátenie požadovaných údajov z rôznych zdrojov, ako sú databázy alebo API.

Ak chcete implementovať autentifikáciu a autorizáciu pomocou webových tokenov JSON (JWT), definujte prekladače pre mutácie registrácie a prihlásenia. Tieto budú spracovávať procesy registrácie a autentifikácie používateľov. Potom vytvorte prekladač dotazov na načítanie údajov, ktorý bude prístupný iba overeným a autorizovaným používateľom.

Najprv však definujte funkcie na generovanie a overenie JWT. V resolvers.js súbor, začnite pridaním nasledujúcich importov.

const User = require("../models/user");
const jwt = require('jsonwebtoken');
const secretKey = process.env.SECRET_KEY;

Do súboru .env nezabudnite pridať tajný kľúč, ktorý budete používať na podpisovanie webových tokenov JSON.

SECRET_KEY = '';

Ak chcete vygenerovať autentifikačný token, zahrňte nasledujúcu funkciu, ktorá tiež špecifikuje jedinečné atribúty pre token JWT, napr. čas vypršania platnosti. Okrem toho môžete začleniť ďalšie atribúty, napríklad vydané v čase, na základe vašich špecifických požiadaviek aplikácie.

functiongenerateToken(user) {
const token = jwt.sign(
{ id: user.id, role: user.role },
secretKey,
{ expiresIn: '1h', algorithm: 'HS256' }
 );

return token;
}

Teraz implementujte logiku overenia tokenov na overenie tokenov JWT zahrnutých v nasledujúcich požiadavkách HTTP.

functionverifyToken(token) {
if (!token) {
thrownewError('Token not provided');
}

try {
const decoded = jwt.verify(token, secretKey, { algorithms: ['HS256'] });
return decoded;
} catch (err) {
thrownewError('Invalid token');
}
}

Táto funkcia vezme token ako vstup, overí jeho platnosť pomocou zadaného tajného kľúča a vráti dekódovaný token, ak je platný, inak vyvolá chybu označujúcu neplatný token.

Definujte API Resolvery

Ak chcete definovať resolvery pre GraphQL API, musíte načrtnúť špecifické operácie, ktoré bude spravovať, v tomto prípade operácie registrácie používateľa a prihlásenia. Najprv vytvorte a riešiteľov objekt, ktorý bude uchovávať funkcie resolvera, potom definujte nasledujúce operácie mutácie:

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');
}
}
},

The Registrovať mutácia spracováva registračný proces pridaním nových užívateľských údajov do databázy. Kým Prihlásiť sa mutácia spravuje prihlasovanie používateľov – pri úspešnej autentifikácii vygeneruje token JWT a v odpovedi vráti správu o úspechu.

Teraz zahrňte nástroj na prekladanie dotazov na získavanie používateľských údajov. Aby ste zabezpečili, že tento dotaz bude prístupný len pre overených a autorizovaných používateľov, zahrňte autorizačnú logiku na obmedzenie prístupu iba na používateľov s Admin úlohu.

Dotaz v podstate najprv skontroluje platnosť tokenu a potom rolu používateľa. Ak je kontrola oprávnenia úspešná, dotaz prekladača bude pokračovať v načítaní a vrátení údajov používateľov z databázy.

 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');
}
},
},
};

Nakoniec spustite vývojový server:

node server.js

Úžasné! Teraz pokračujte a otestujte funkčnosť rozhrania API pomocou karantény Apollo Server API vo vašom prehliadači. Môžete napríklad použiť Registrovať mutácia na pridanie nových užívateľských údajov do databázy a potom, Prihlásiť sa mutácia na autentifikáciu užívateľa.

Nakoniec pridajte token JWT do sekcie hlavičky autorizácie a pokračujte v dotazovaní databázy na používateľské údaje.

Zabezpečenie GraphQL API

Autentifikácia a autorizácia sú kľúčové komponenty pre zabezpečenie GraphQL API. Napriek tomu je dôležité si uvedomiť, že samotné nemusia postačovať na zabezpečenie komplexnej bezpečnosti. Mali by ste implementovať ďalšie bezpečnostné opatrenia, ako je overenie vstupu a šifrovanie citlivých údajov.

Prijatím komplexného bezpečnostného prístupu môžete chrániť svoje rozhrania API pred rôznymi potenciálnymi útokmi.