paint-brush
Ահա թե ինչպես են ծրագրավորողները կարող համոզվել, որ զգայուն տվյալները պատահաբար չեն հասնում մեկ այլ սարքիկողմից@dougsillars1
Նոր պատմություն

Ահա թե ինչպես են ծրագրավորողները կարող համոզվել, որ զգայուն տվյալները պատահաբար չեն հասնում մեկ այլ սարքի

կողմից Doug8m2024/12/25
Read on Terminal Reader

Չափազանց երկար; Կարդալ

Մշակողները պետք է ապահովեն, որ հավելվածում պահվող զգայուն տվյալները պատահականորեն չհանձնվեն այլ կողմին: Այս ձեռնարկը ձեզ կսովորեցնի, թե ինչպես կարելի է ստեղծել Remix հավելված՝ օգտագործելով Clerk-ը որպես նույնականացման շերտ: Այնուհետև մենք օգտագործում ենք Row Level Security-ը Neon-ից՝ հաճախորդների տվյալները պաշտպանելու համար:
featured image - Ահա թե ինչպես են ծրագրավորողները կարող համոզվել, որ զգայուն տվյալները պատահաբար չեն հասնում մեկ այլ սարքի
Doug HackerNoon profile picture
0-item

Դուք երբևէ ստացել եք ձեր հարևանի փաթեթը ձեր մուտքի դռան մոտ: (Գուցե նույնիսկ պատահաբար բացե՞լ եք այն): Որպես հավելված մշակողներ, ձեր խնդիրն է ապահովել, որ ձեր հավելվածում պահվող զգայուն տվյալները պատահաբար չհանձնվեն այլ կողմին:


Հաճախորդների տվյալները ապահով պահելու համար մատչելի են բազմաթիվ տեխնիկա, և շատերը չափազանց բարդ են և դժվար իրագործելի: Իդեալում, կարելի է ապահովել հաճախորդների բոլոր տվյալները մեկ տվյալների բազայում՝ պահպանելով գործառույթի դիզայնը պարզ և անվտանգ:


Տողերի մակարդակի անվտանգությունը (RLS) տվյալների բազայի աղյուսակի ներսում տվյալների որոշակի տողերի մուտքն ապահովելու և վերահսկելու ունակություն է: Այն հզոր գործիք է, որը թույլ է տալիս պահպանել ձեր հաճախորդների բոլոր տվյալները մեկ տվյալների բազայում՝ առանց որևէ մտահոգության՝ կապված հաշվում տվյալների արտահոսքի հետ: Այնուամենայնիվ, RLS-ի ճիշտ իրականացումը կարող է բարդ գործընթաց լինել, որը ներառում է մուտքի մանրամասները ձեր տվյալների բազայի թույլտվությունների հետ համատեղելը: Neon Authorize-ը հեշտացնում է այս գործընթացը՝ ավտոմատ կերպով ինտեգրելով նույնականացումը ձեր OAuth մատակարարից ձեր PostgreSQL տվյալների բազայի հետ:


Neon Authorize-ն օգտագործում է ձեր գոյություն ունեցող նույնականացման շերտը՝ յուրաքանչյուր մուտք գործած օգտվողին նույնականացնելու համար և ձեր տվյալների բազայի բոլոր տվյալները կապում է նրանց մուտքի հավատարմագրերի հետ: Սա երաշխավորում է, որ տվյալների բազայում պահվող տվյալները կարող են մուտք գործել միայն մուտք գործած օգտվողների համար, և որ միայն մուտք գործած օգտվողները կարող են տեսնել իրենց տվյալները:


Այս ձեռնարկը ձեզ կսովորեցնի, թե ինչպես ստեղծել Remix հավելված՝ օգտագործելով Clerk-ը որպես նույնականացման շերտ: Clerk-ը օգտատերերի նույնականացման և կառավարման հանրաճանաչ գործիք է: Դուք կօգտագործեք Neon Postgres-ը որպես ձեր տվյալների շերտ և կօգտագործեք Neon Authorize-ը, որպեսզի ապահովի բոլոր տվյալները յուրաքանչյուր մուտք գործած հաճախորդի համար: Աղյուսակի յուրաքանչյուր տող կնշանակի userID, որը տրամադրվում է Clerk-ի կողմից: Միայն userID-ով վավերացվածները կարող են շփվել տողում գտնվող տվյալների հետ:


Մեր օրինակելի հավելվածը պարզ է. այն գրանցում է յուրաքանչյուր մուտք RLS տվյալների բազա՝ օգտագործելով userID-ը: Երբ էջը բեռնվի, կցուցադրվեն վավերացված օգտատիրոջ վերջին 10 մուտքերը, և այլ օգտվողի տվյալներ (պահված նույն PostgreSQL աղյուսակում) չեն հայտնվի։ Եկեք սկսենք:

Remix հավելվածի ստեղծում


Սկսեք ստեղծելով 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 արմատային գրացուցակում.


 import { vitePlugin as remix } from "@remix-run/dev"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [remix()], });


Նախքան որևէ զարգացում կատարելը, մենք պետք է հաշիվներ ստեղծենք Clerk-ում և Neon-ում՝ նրանց ծառայություններից օգտվելու համար.


Clerk և Neon օրինակների ստեղծում

Գործավարուհի

Մուտք գործեք Clerk վահանակ՝ նոր նախագիծ ստեղծելու համար:

  1. Ձախ նավարկությունում ընտրեք API ստեղներ :

    1. Արագ պատճենման վանդակում ընտրեք Remix և պատճենեք շրջակա միջավայրի փոփոխականները:
    2. Տեղադրեք դրանք ձեր կոդի մեջ .env ֆայլի մեջ:
  2. Ձախ նավարկությունում ընտրեք « JWT կաղապարներ. »

    1. Ստեղծեք ձևանմուշ (ես իմն անվանել եմ « նեոն-ռեմիքս »):
    2. Պատճենեք JWKS վերջնակետի URL-ը հետագա օգտագործման համար:

Նեոն

  1. Մուտք գործեք Neon վահանակ և ստեղծեք նոր նախագիծ:

  2. Ձախ նավիգացիոն ընտրացանկից ընտրեք Թույլտվություն :

  3. Ստեղծեք նոր մատակարար և տեղադրեք Clerk JWKS URL-ը , որը նախկինում պատճենել եք Clerk-ից:


Օրինակը ստեղծելուց հետո սեղմեք «Սկսել»: Կողքի վահանակը կբացվի մի շարք քայլերով՝ ձեր Neon Authorize-ի ինտեգրումն ավարտելու համար:

Սկսելու կարգավորումը ձեզ տրամադրում է քայլեր՝ կարգավորելու հիմնական լիազորման նախագիծը Clerk-ի հետ:

 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 հավելվածի համար: Todos հավելվածի համար Neon-ից տրամադրված կաթսայատան կոդը օգտագործելու փոխարեն մենք կստեղծենք login_history աղյուսակ և դրա վրա կտեղադրենք RLS: Բացեք SQL Editor-ը Neon վահանակում և գործարկեք ստորև նշված կոդը: 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-...


Remix հավելվածի ստեղծում

Հավելվածն այժմ պատրաստ է ստեղծման։ Ամբողջական կոդը հասանելի է 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 հաշիվ և դիտել կողք կողքի տվյալները տարբեր օգտվողների համար.



Նկատի ունեցեք, որ մուտքի ժամանակները համընկնում են, բայց տվյալների բազայում օգտագործելով Row-Level Security, դուք կկանխեք տվյալների արտահոսքը հաշիվներից: Տողերը կարող են արդյունահանվել և ցուցադրվել միայն վավերացված օգտվողի համար:


Եզրակացություն

Տվյալների գաղտնի պահելը օգտագործման կարևորագույն դեպք է: Քանի որ հավելվածները հաճախ պահում են անձնական տեղեկատվություն, այն պետք է ապահովված լինի՝ տվյալները ճիշտ ձեռքերում պահելու համար: Սպառողներն ունեն ավելի ու ավելի շատ իրավական պաշտպանություն, ինչպիսին է GDPR-ը, և Neon Authorize-ի նման գործիքները հեշտացնում են Row Level Security-ի ներդրումը` ձեր հաճախորդի տվյալները պաշտպանելու համար:


Այս գրառման մեջ մենք անցել ենք այն քայլերը, որոնք անհրաժեշտ են նեոնային տվյալների բազայում շարքի մակարդակի անվտանգությունը միացնելու համար: Մեր հաճախորդի տվյալների հետ RLS-ի օգտագործումը երաշխավորում է, որ միայն մուտք գործած օգտվողն ունի իր սեփական տվյալները հանելու հավատարմագրերը:


Այսօր Neon-ի միջոցով ձեր հավելվածին ավելացրեք Row Layer Security :