ოდესმე მიგიღიათ მეზობლის ამანათი თქვენს შესასვლელთან? (იქნებ შემთხვევით გახსენი?) იქნებ ვინმესთვის მგრძნობიარე ხმოვანი ფოსტა დაგრჩათ? როგორც აპლიკაციის დეველოპერები, თქვენი ამოცანაა უზრუნველყოთ, რომ თქვენს აპლიკაციაში შენახული სენსიტიური მონაცემები შემთხვევით არ გადაეცეს სხვა მხარეს.
არსებობს მრავალი ტექნიკა მომხმარებლის მონაცემების უსაფრთხოდ შესანახად და ბევრი მათგანი ძალიან რთული და რთულად განსახორციელებელია. იდეალურ შემთხვევაში, შეიძლება მომხმარებელთა ყველა მონაცემის დაცვა ერთ მონაცემთა ბაზაში - ფუნქციის დიზაინი მარტივი და უსაფრთხო იყოს.
მწკრივის დონის უსაფრთხოება (RLS) არის მონაცემთა ბაზის ცხრილის შიგნით მონაცემთა კონკრეტულ მწკრივებზე წვდომის უზრუნველყოფის და კონტროლის შესაძლებლობა. ეს არის ძლიერი ინსტრუმენტი, რომელიც საშუალებას გაძლევთ შეინახოთ თქვენი მომხმარებლის ყველა მონაცემი ერთ მონაცემთა ბაზაში, ყოველგვარი შეშფოთების გარეშე ანგარიშებზე მონაცემების გაჟონვის შესახებ. თუმცა, RLS-ის სწორად დანერგვა შეიძლება იყოს რთული პროცესი, რომელიც მოიცავს შესვლის დეტალების გაერთიანებას თქვენი მონაცემთა ბაზის ნებართვებთან. Neon Authorize ამარტივებს ამ პროცესს თქვენი OAuth პროვაიდერის ავტორიზაციის ავტომატურად ინტეგრირებით თქვენს PostgreSQL მონაცემთა ბაზასთან.
Neon Authorize იყენებს თქვენს არსებულ ავტორიზაციის ფენას ყველა შესული მომხმარებლის იდენტიფიცირებისთვის და აკავშირებს თქვენს მონაცემთა ბაზაში არსებულ ყველა მონაცემს მათ შესვლის სერთიფიკატებთან. ეს უზრუნველყოფს, რომ მონაცემთა ბაზაში შენახულ მონაცემებზე წვდომა მხოლოდ შესული მომხმარებლებისთვის არის შესაძლებელი — და რომ მხოლოდ სისტემაში შესულ მომხმარებლებს შეუძლიათ მათი მონაცემების ნახვა.
ეს გაკვეთილი გაგაცნობთ, თუ როგორ უნდა შექმნათ Remix აპი Clerk-ის, როგორც ავტორიზაციის ფენის გამოყენებით. Clerk არის პოპულარული მომხმარებლის ავთენტიფიკაციისა და მართვის ინსტრუმენტი. თქვენ გამოიყენებთ Neon Postgres-ს, როგორც მონაცემთა ფენას და გამოიყენებთ Neon Authorize-ს, რათა უზრუნველყოთ ყველა მონაცემი თითოეული შესული მომხმარებლისთვის. ცხრილის თითოეული მწკრივი მიუთითებს მომხმარებლის ID-ს, რომელიც მოწოდებულია კლერკის მიერ. მხოლოდ მომხმარებლის ID-ით ავთენტიფიცირებულებს შეუძლიათ მწკრივში მოცემულ მონაცემებთან ურთიერთობა.
ჩვენი ნიმუშის აპლიკაცია მარტივია - ის იწერს ყველა შესვლას RLS მონაცემთა ბაზაში მომხმარებლის ID-ის გამოყენებით. როდესაც გვერდი იტვირთება, გამოჩნდება ავტორიზებული მომხმარებლის ბოლო 10 შესვლა და არ გამოჩნდება სხვა მომხმარებლის მონაცემები (შენახული იმავე PostgreSQL ცხრილში). მოდი დავიწყოთ!
დაიწყეთ Remix აპლიკაციის შექმნით და დამოკიდებულებების დაყენებით ქვემოთ მოცემული კოდის ფრაგმენტის გამოყენებით. უფრო დეტალური ინსტრუქციებისთვის იხილეთ Remix-ის სწრაფი დაწყების სახელმძღვანელო .
##make a directory and initialise your NPM project mkdir neon-authorize-remix-clerk-app cd neon-authorize-remix-clerk-app npm init -y ## install runtime dependecies for Remix npm i @remix-run/node @remix-run/react @remix-run/serve isbot@4 react react-dom @remix-run/router drizzle-orm npm install @neondatabase/serverless npm install @clerk/remix npm i -D @remix-run/dev vite
ვინაიდან Remix იყენებს Vite-ს, Javascript-ის აგების ხელსაწყოს, შექმენით vite.config.js
root დირექტორიაში:
import { vitePlugin as remix } from "@remix-run/dev"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [remix()], });
სანამ რაიმე განვითარებას გავაკეთებთ, ჩვენ უნდა შევქმნათ ანგარიშები Clerk-სა და Neon-ში, რომ გამოვიყენოთ მათი სერვისები:
შედით Clerk-ის საინფორმაციო დაფაში ახალი პროექტის შესაქმნელად.
მარცხენა ნავიგაციაში აირჩიეთ API Keys .
.env
ფაილში თქვენს კოდში.მარცხენა ნავიგაციაში აირჩიეთ “ JWT შაბლონები. ”
შედით ნეონის კონსოლში და შექმენით ახალი პროექტი.
მარცხენა ნავიგაციის მენიუდან აირჩიეთ ავტორიზაცია .
შექმენით ახალი პროვაიდერი და ჩასვით Clerk JWKS URL , რომელიც ადრე დააკოპირეთ Clerk-დან.
ინსტანციის შექმნის შემდეგ დააჭირეთ ღილაკს "დაწყება". გაიხსნება გვერდითი პანელი მთელი რიგი ნაბიჯებით თქვენი Neon Authorize-ის ინტეგრაციის დასასრულებლად.
დაწყების დაყენება გთავაზობთ ნაბიჯებს კლერკთან ერთად ავტორიზაციის ძირითადი პროექტის დასაყენებლად.
1. Set up Neon Extension and Roles Privileges. Run these steps in the Dashboard. 2. Grant privileges to the roles in the neondb database.
მოწოდებული კოდი არის todos აპისთვის. იმის ნაცვლად, რომ გამოვიყენოთ Neon-დან მოწოდებული boilerplate კოდი todos აპისთვის, ჩვენ შევქმნით login_history
ცხრილს და დავაყენებთ მასზე RLS-ს. გახსენით SQL რედაქტორი ნეონის დაფაზე და გაუშვით ქვემოთ მოცემული კოდი. login_history
ცხრილი გამოყენებული იქნება თითოეული მომხმარებლის შესვლის დროების შესანახად.
გაითვალისწინეთ, რომ
login_history
აქვს მხოლოდ სამი სვეტი: id, user_id და login_at. ბოლო ორი სვეტი აჩვენებს აპლიკაციაში უახლესი შესვლას.
CREATE TABLE login_history ( id bigint generated by default as identity primary key, user_id text not null default (auth.user_id()), login_at timestamp not null default now() ); -- 1st enable row level security for your table ALTER TABLE login_history ENABLE ROW LEVEL SECURITY; -- 2nd create policies for your table CREATE POLICY "Individuals can add login." ON login_history FOR INSERT TO authenticated WITH CHECK ((select auth.user_id()) = user_id); CREATE POLICY "Individuals can view their own logins. " ON login_history FOR SELECT TO authenticated USING ((select auth.user_id()) = user_id);
დაამატეთ მოწოდებული გარემოს ცვლადები თქვენს .env
დაყენების ამ ნაბიჯების დასრულების შემდეგ, თქვენს .env
უნდა ჰქონდეს ოთხი ცვლადი: ორი Clerk-დან და ორი Neon-დან:
CLERK_PUBLISHABLE_KEY=pk_test_.... CLERK_SECRET_KEY=sk_test_... # Database owner connection string DATABASE_URL='postgresql://neondb_owner:...' # Neon "authenticated" role connection string DATABASE_AUTHENTICATED_URL='postgresql://authenticated@ep-...
აპლიკაცია ახლა მზად არის ასაშენებლად. სრული კოდი ხელმისაწვდომია GitHub- ზე, მაგრამ აქ ხაზგასმულია ყველაზე მნიშვნელოვანი ფუნქციები. აპლიკაციის ბირთვი არის app/routes/_index.tsx
:
export const loader: LoaderFunction = async (args) => { const { userId, getToken } = await getAuth(args); if (!userId) { return redirect("/sign-in"); } const authToken = await getToken(); console.log(userId); if (!authToken) { return null; } const DATABASE_AUTHENTICATED_URL= process.env.NEXT_PUBLIC_DATABASE_AUTHENTICATED_URL; try { const sql = neon(DATABASE_AUTHENTICATED_URL ?? '', { authToken, }); const loginResponse = await sql(`INSERT INTO login_history ("user_id") VALUES ($1) RETURNING *`,[userId]); // Retrieve last 10 logins const last10LoginsResponse = await sql(`SELECT * FROM login_history WHERE user_id = $1 ORDER BY login_at DESC LIMIT 10`, [userId]); console.log(`loginResponse: ${JSON.stringify(loginResponse)}`); return last10LoginsResponse as Array<LoginHistory>; } catch (error) { console.error(`Error inserting into login_history table: ${error.message}`); console.error(`Error details: ${JSON.stringify(error)}`); throw error; } }
LoaderFunction
_index.tsx
ფაილში ასრულებს დავალებებს სერვერზე კლიენტისთვის გვერდის გაფორმებამდე. ამ აპლიკაციაში ჩამტვირთავი ასრულებს აპლიკაციის მძიმე აწევას.
ფუნქცია ჯერ ამოწმებს, არ არის თუ არა მომხმარებელი შესული და შემდეგ გადამისამართებს მომხმარებელს /sign-in
გვერდზე. შესვლის გვერდის კონფიგურაცია შესაძლებელია Clerk-ის საინფორმაციო დაფაზე, რათა მიიღოს შესვლის სხვადასხვა ტიპები, როგორიცაა Google და ელექტრონული ფოსტის შესვლა:
შესვლის გვერდის შესაქმნელად, გადადით Clerk-ის დაფაზე და დააყენეთ პროექტისთვის საჭირო შესვლის მეთოდები.
თუ მომხმარებელი შესულია სისტემაში, ფუნქცია ამოიღებს userId
ს და authToken
Clerk-დან. ეს მნიშვნელობები აუცილებელია მომხმარებლის შესვლის უზრუნველსაყოფად, შემდეგ კი შეგიძლიათ გამოიყენოთ userId
თქვენი მონაცემთა ბაზის თითოეული მწკრივის შესავსებად.
RLS-ით დაცულ მონაცემთა ბაზაში ცვლილებების შესატანად, თქვენ უნდა ამოიღოთ DATABASE_AUTHENTCATED_URL
გარემოს ცვლადებიდან.
RLS უსაფრთხოების განხორციელების ძირითადი ლოგიკა LoaderFunction
შია. SQL Neon ინსტანციის ინიციალიზაცია ხდება გარემოს ცვლადების და ავტორიზაციის ნიშნის გამოყენებით. loginResponse
ფუნქცია ახდენს SQL ზარს და ათავსებს user_id-ს (და მიმდინარე დროს) PostgreSQL მონაცემთა ბაზაში, რის შემდეგაც last10LoginsResponse
ფუნქცია ითხოვს DB-ს 10 უახლესი შესვლისთვის.
საბოლოოდ, last10LoginsResponse
ბრუნდება ჩამტვირთავი ფუნქციიდან.
Index()
ფუნქცია _index.tsx
ფაილში ასახავს გვერდის განლაგებას, როგორც ნაჩვენებია ქვემოთ მოცემულ სნიპეტში:
export default function Index() { const logins = useLoaderData(); return ( <div> <h1>Signed in</h1> <p>You are signed in!</p> <p> <UserButton /></p> <div> <h1>Recent Logins</h1> {logins?.map((logins) => ( <li key={logins.id}> {logins.user_id} login at: {logins.login_at} </li> ))} </div> <p>< SignOutButton > Sign Out</ SignOutButton ></p> </div> ); }
ზემოთ მოცემული კოდი იღებს პასუხს LoaderFunction
დან, რომელიც შეიცავს ბოლო 10 შესვლის ჩანაწერს. ეს პასუხი აყალიბებს გვერდს, რომელიც ეუბნება მომხმარებელს, რომ შესულია, ჩამოთვლის მათ ბოლო 10 შესვლას და აჩვენებს ღილაკს გასვლა, როგორც ეს ნაჩვენებია ქვემოთ:
ამ მაგალითში, user_id
ასევე ნაჩვენებია, რათა ნათლად მიუთითებდეს, რომ მხოლოდ შესული მომხმარებლის შესვლის მონაცემები ჩანს.
ინკოგნიტო ფანჯრის გამოყენებით შეგიძლიათ შეხვიდეთ მეორე Google ანგარიშით და ნახოთ გვერდიგვერდ მონაცემები სხვადასხვა მომხმარებლისთვის:
გაითვალისწინეთ, რომ შესვლის დრო ერთმანეთს ემთხვევა, მაგრამ მონაცემთა ბაზაში მწკრივის დონის უსაფრთხოების გამოყენებით, თქვენ თავიდან აიცილებთ მონაცემთა გაჟონვას ანგარიშებზე. რიგების ამოღება და ჩვენება შესაძლებელია მხოლოდ ავტორიზებული მომხმარებლისთვის.
მონაცემთა კონფიდენციალურობის შენარჩუნება კრიტიკული გამოყენების შემთხვევაა. იმის გამო, რომ აპლიკაციები ხშირად ინახავს პირად ინფორმაციას, ის დაცული უნდა იყოს მონაცემების სწორ ხელში შესანახად. მომხმარებლებს აქვთ უფრო და უფრო მეტი სამართლებრივი დაცვა, როგორიცაა GDPR, და ინსტრუმენტები, როგორიცაა Neon Authorize, აადვილებს მწკრივის დონის უსაფრთხოების დანერგვას თქვენი მომხმარებლის მონაცემების დასაცავად.
ამ პოსტში ჩვენ გავიარეთ ნაბიჯები, რომლებიც საჭიროა Neon მონაცემთა ბაზაში მწკრივის დონის უსაფრთხოების გასააქტიურებლად. ჩვენი მომხმარებლის მონაცემებით RLS-ის გამოყენება უზრუნველყოფს, რომ მხოლოდ სისტემაში შესულ მომხმარებელს აქვს რწმუნებათა სიგელები საკუთარი მონაცემების ამოსაღებად.
დაამატეთ რიგის ფენის უსაფრთხოება თქვენს აპს დღეს Neon-ით.