GraphQL on populaarne alternatiiv traditsioonilisele RESTful API arhitektuurile, pakkudes API-de jaoks paindlikku ja tõhusat andmepäringu- ja manipuleerimiskeelt. Sellega üha kasvav kasutuselevõtt muutub järjest olulisemaks GraphQL API-de turvalisuse prioriteediks seadmine, et kaitsta rakendusi volitamata juurdepääsu ja võimalike andmete eest rikkumisi.

Üks tõhus viis GraphQL API-de turvamiseks on JSON Web Tokens (JWT) rakendamine. JWT-d pakuvad turvalist ja tõhusat meetodit kaitstud ressurssidele juurdepääsu andmiseks ja volitatud toimingute tegemiseks, tagades turvalise suhtluse klientide ja API-de vahel.

Autentimine ja autoriseerimine GraphQL API-des

Erinevalt REST API-dGraphQL API-del on tavaliselt üks lõpp-punkt, mis võimaldab klientidel päringutes dünaamiliselt taotleda erinevas mahus andmeid. Kuigi see paindlikkus on selle tugevus, suurendab see ka võimalike turvarünnete, näiteks katkiste juurdepääsukontrolli haavatavuste ohtu.

Selle riski maandamiseks on oluline rakendada tugevaid autentimis- ja autoriseerimisprotsesse, sealhulgas õigesti määratleda juurdepääsuõigused. Seda tehes garanteerite, et kaitstud ressurssidele pääsevad juurde ainult volitatud kasutajad, ning lõpuks vähendate võimalike turvarikkumiste ja andmete kadumise ohtu.

instagram viewer

Selle projekti koodi leiate sellest GitHub hoidla.

Express.js Apollo serveri seadistamine

Apollo server on laialdaselt kasutatav GraphQL-i serveri rakendus GraphQL API-de jaoks. Saate seda kasutada oma API-de jaoks GraphQL-i skeemide hõlpsaks koostamiseks, lahendajate määratlemiseks ja erinevate andmeallikate haldamiseks.

Express.js Apollo serveri seadistamiseks looge ja avage projekti kaust.

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

Järgmisena käivitage see käsk uue Node.js-projekti lähtestamiseks kasutades npm, sõlme paketihaldur:

npm init --yes

Nüüd installige need paketid.

npm install apollo-server graphql mongoose jsonwebtokens dotenv

Lõpuks looge a server.js faili juurkataloogis ja seadistage oma server selle koodiga:

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-server on seadistatud rakendusega typeDefs ja lahendajad parameetrid, täpsustades skeemi ja toimingud, mida API saab käsitleda. The Sisu suvand konfigureerib req objekti iga lahendaja konteksti, mis võimaldab serveril pääseda juurde päringu spetsiifilistele üksikasjadele, nagu päise väärtused.

Looge MongoDB andmebaas

Andmebaasiühenduse loomiseks kõigepealt looge MongoDB andmebaas või looge MongoDB Atlases klaster. Seejärel kopeerige pakutud andmebaasiühenduse URI string ja looge a .env faili ja sisestage ühenduse string järgmiselt:

MONGO_URI=""

Määratlege andmemudel

Määrake andmemudel Mongoose'i abil. Loo uus models/user.js faili ja lisage järgmine kood:

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

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

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

Määratlege GraphQL-i skeem

GraphQL API-s määratleb skeem päringute esitatavate andmete struktuuri, samuti saadaolevad toimingud (päringud ja mutatsioonid), mida saate teha andmetega suhtlemiseks rakenduse kaudu API.

Skeemi määratlemiseks looge oma projekti juurkataloogis uus kaust ja pange sellele nimi graphql. Lisage sellesse kausta kaks faili: typeDefs.js ja solvers.js.

Aastal typeDefs.js faili, lisage järgmine kood:

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;

Looge GraphQL API jaoks lahendajad

Lahendaja funktsioonid määravad, kuidas andmeid tuuakse vastuseks kliendi päringutele ja mutatsioonidele, samuti muudele skeemis määratletud väljadele. Kui klient saadab päringu või mutatsiooni, käivitab GraphQL-server vastavad lahendajad, et töödelda ja tagastada nõutavad andmed erinevatest allikatest, näiteks andmebaasidest või API-dest.

Autentimise ja autoriseerimise rakendamiseks JSON-i veebilubade (JWT-de) abil määrake registri- ja sisselogimismutatsioonide jaoks lahendajad. Need haldavad kasutajate registreerimise ja autentimise protsesse. Seejärel looge andmete toomise päringu lahendaja, mis on juurdepääsetav ainult autentitud ja volitatud kasutajatele.

Kuid kõigepealt määratlege funktsioonid JWT-de genereerimiseks ja kontrollimiseks. Aastal solvers.js faili, lisage kõigepealt järgmised impordid.

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

Lisage .env-faili kindlasti salavõti, mida kasutate JSON-i veebilubade allkirjastamiseks.

SECRET_KEY = '';

Autentimisloa genereerimiseks lisage järgmine funktsioon, mis määrab ka JWT-märgi kordumatud atribuudid, nt aegumisaja. Lisaks saate lisada muid atribuute (nt välja antud õigel ajal vastavalt teie rakenduse nõuetele).

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

return token;
}

Nüüd rakendage loa kontrollimise loogikat, et kinnitada järgmistes HTTP-päringutes sisalduvad JWT-märgid.

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

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

See funktsioon võtab sisendiks märgi, kontrollib selle kehtivust määratud salajase võtmega ja tagastab dekodeeritud märgi, kui see on kehtiv, vastasel juhul kuvab veateate, mis viitab kehtetule märgile.

Määratlege API lahendajad

GraphQL API lahendajate määratlemiseks peate kirjeldama konkreetseid toiminguid, mida see haldab, antud juhul kasutaja registreerimis- ja sisselogimistoimingud. Esiteks looge a lahendajad objekt, mis sisaldab lahendaja funktsioone, seejärel määratlege järgmised mutatsioonitoimingud:

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 Registreeri mutatsioon tegeleb registreerimisprotsessiga, lisades andmebaasi uued kasutajaandmed. Samal ajal kui Logi sisse mutatsioon haldab kasutajate sisselogimisi – eduka autentimise korral genereerib see JWT märgi ja tagastab vastuses eduteate.

Nüüd kaasake kasutajaandmete toomiseks päringu lahendaja. Tagamaks, et sellele päringule pääsevad juurde ainult autentitud ja volitatud kasutajad, lisage autoriseerimisloogika, et piirata juurdepääsu ainult kasutajatele, kellel on Admin rolli.

Põhimõtteliselt kontrollib päring esmalt märgi kehtivust ja seejärel kasutaja rolli. Kui autoriseerimiskontroll on edukas, jätkab lahendaja päring kasutajate andmete toomist ja tagastamist andmebaasist.

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

Lõpuks käivitage arendusserver:

node server.js

Vinge! Nüüd jätkake ja testige API funktsionaalsust, kasutades oma brauseris Apollo Serveri API liivakasti. Näiteks võite kasutada Registreeri mutatsiooni, et lisada andmebaasi uusi kasutajaandmeid ja seejärel Logi sisse mutatsioon kasutaja autentimiseks.

Lõpuks lisage autoriseerimispäise jaotisesse JWT-märk ja jätkake kasutajaandmete andmebaasist päringu esitamisega.

GraphQL API-de turvamine

Autentimine ja autoriseerimine on GraphQL API-de turvamise olulised komponendid. Sellegipoolest on oluline mõista, et neist üksi ei pruugi igakülgse turvalisuse tagamiseks piisata. Peaksite rakendama täiendavaid turvameetmeid, nagu sisendi valideerimine ja tundlike andmete krüpteerimine.

Võttes kasutusele tervikliku turvalisuse lähenemisviisi, saate kaitsta oma API-sid erinevate võimalike rünnakute eest.