Ви коли-небудь отримували пакунок від свого сусіда біля вхідних дверей? (Можливо, навіть випадково відкрив його?) Можливо, у вас залишилося конфіденційне голосове повідомлення для когось іншого? Як розробники програм, ваша робота полягає в тому, щоб конфіденційні дані, що зберігаються у вашій програмі, не були випадково доставлені іншій стороні. Існує багато методів, доступних для безпечного зберігання даних клієнтів, і багато з них дуже складні та важкі для впровадження. В ідеалі можна було б захистити всі дані клієнта в одній базі даних, зберігаючи дизайн функції простим і безпечним. — це можливість захищати та контролювати доступ до певних рядків даних у таблиці бази даних. Це потужний інструмент, який дозволяє зберігати всі ваші клієнтські дані в одній базі даних, не турбуючись про витік даних між обліковими записами. Однак правильна реалізація RLS може бути складним процесом, пов’язаним із поєднанням даних для входу та дозволів бази даних. спрощує цей процес, автоматично інтегруючи автентифікацію від вашого постачальника OAuth у вашу базу даних PostgreSQL. Безпека на рівні рядків (RLS) Neon Authorize Neon Authorize використовує ваш існуючий рівень автентифікації для ідентифікації кожного користувача, який увійшов у систему, і пов’язує всі дані у вашій базі даних з їхніми обліковими даними для входу. Це гарантує, що дані, які зберігаються в базі даних, будуть доступні лише користувачам, які ввійшли в систему, і що лише користувачі, які ввійшли в систему, можуть бачити свої дані. У цьому посібнику ви дізнаєтеся, як створити програму Remix, використовуючи Clerk як рівень автентифікації. — популярний інструмент аутентифікації та керування користувачами. Ви використовуватимете Neon Postgres як рівень даних і використовуватимете Neon Authorize, щоб захистити всі дані кожного клієнта, який увійшов у систему. Кожен рядок у таблиці позначатиме ідентифікатор користувача, який надає Клерк. Тільки ті, хто пройшов автентифікацію за допомогою ідентифікатора користувача, можуть взаємодіяти з даними в рядку. Clerk Наш зразок програми простий — він записує кожен вхід до бази даних RLS за допомогою ідентифікатора користувача. Коли сторінка завантажується, відображатимуться останні 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, щоб створити новий проект. На панелі навігації ліворуч виберіть . Ключі API У полі «Швидке копіювання» виберіть «Ремікс» і скопіюйте змінні середовища. Вставте їх у файл у своєму коді. .env У лівій панелі навігації виберіть « » Шаблони JWT. Створіть шаблон (я назвав свій « »). neon-remix Скопіюйте для подальшого використання. URL-адресу кінцевої точки JWKS Неон Увійдіть у консоль Neon і створіть новий проект. У навігаційному меню ліворуч виберіть . Авторизувати Створіть нового постачальника та вставте , яку ви скопіювали з Clerk раніше. URL-адресу Clerk JWKS Створивши екземпляр, натисніть «Почати». Відкриється бічна панель із низкою кроків для завершення інтеграції 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. Замість використання наданого шаблонного коду від Neon для програми todos ми створимо таблицю і налаштуємо RLS на ній. Відкрийте редактор SQL на інформаційній панелі Neon і запустіть наведений нижче код. Таблиця буде використовуватися для зберігання часу входу для кожного користувача. login_history login_history Зверніть увагу, що має лише три стовпці: id, user_id і login_at. Останні два стовпці відображатимуть останні входи в програму. login_history 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 Після завершення цих кроків налаштування ваш має мати чотири змінні: дві від Clerk і дві від Neon: .env 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 Функція спочатку перевіряє, чи не ввійшов користувач, а потім перенаправляє користувача на сторінку . Сторінку входу можна налаштувати на інформаційній панелі Clerk для прийняття різних типів входу, як-от Google та електронної пошти: /sign-in Щоб створити сторінку входу, перейдіть до інформаційної панелі Clerk і налаштуйте необхідні методи входу для проекту. Якщо користувач увійшов у систему, функція отримує і від Clerk. Ці значення необхідні для того, щоб переконатися, що користувач увійшов у систему, а потім ви можете використовувати для заповнення кожного рядка у вашій базі даних. userId authToken userId Щоб внести зміни в базу даних, захищену RLS, потрібно отримати зі змінних середовища. DATABASE_AUTHENTCATED_URL Основна логіка реалізації безпеки RLS лежить у . Екземпляр SQL Neon ініціалізується за допомогою змінних середовища та маркера автентифікації. Функція здійснює виклик SQL і вставляє user_id (і поточний час) у базу даних PostgreSQL, після чого функція запитує в БД 10 останніх входів. LoaderFunction loginResponse last10LoginsResponse Нарешті, повертається функцією завантажувача. 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> ); } Наведений вище код отримує відповідь із функції , яка містить останні 10 записів для входу. Ця відповідь створює сторінку, яка повідомляє користувачеві, що він увійшов, перераховує його останні 10 логінів і показує кнопку «Вийти», як показано нижче: LoaderFunction У цьому прикладі також відображається, щоб чітко вказати, що видимі лише дані для входу користувача, який увійшов у систему. user_id Використовуючи вікно анонімного перегляду, ви можете увійти за допомогою другого облікового запису Google і паралельно переглядати дані для різних користувачів: Зауважте, що час входу збігається, але використовуючи захист на рівні рядків у базі даних, ви запобіжите витоку даних між обліковими записами. Рядки можуть бути витягнуті та відображені лише для автентифікованого користувача. Висновок Зберігання конфіденційності даних є критично важливим випадком використання. Оскільки програми часто зберігають конфіденційну інформацію, її потрібно захищати, щоб дані залишалися в правильних руках. Споживачі отримують дедалі більше правового захисту, як-от GDPR, а такі інструменти, як Neon Authorize, спрощують впровадження захисту на рівні рядків для захисту даних клієнтів. У цій публікації ми розглянули кроки, необхідні для ввімкнення безпеки на рівні рядків у базі даних Neon. Використання RLS із даними нашого клієнта гарантує, що лише користувач, який увійшов у систему, матиме облікові дані для отримання власних даних. Додайте у свою програму вже сьогодні за допомогою Neon. Row Layer Security