Внешняя безопасность – это методы и меры, принимаемые для защиты пользовательского интерфейса и клиентских компонентов веб-приложения.
Регулярно обновляйте зависимости📦
- Регулярно обновляйте React JS и его зависимости до последних версий, чтобы получать исправления безопасности и исправления ошибок.
- Используйте такие инструменты, как аудит npm или аудит пряжи, чтобы выявить и устранить уязвимости в зависимостях вашего проекта.
- Используйте Snyk — для мониторинга и защиты зависимостей.
- Используйте Dependabot — автоматическое обновление зависимостей.
Предотвращение межсайтового скриптинга (XSS)🛡️
Почти 65% веб-сайтов подвержены XSS-уязвимостям, обнаруженным в современных веб-приложениях.
- Используйте JSX для рендеринга динамического контента — значения автоматически экранируются для предотвращения XSS-атак.
- Избегайте использования dangerouslySetInnerHTML без крайней необходимости и тщательно очищайте пользовательский контент перед рендерингом.
В React.js опасноSetInnerHTML — это свойство, которое позволяет вам вставлять необработанный HTML в выходные данные компонента. Эту функцию следует использовать с осторожностью, поскольку неправильное использование может подвергнуть ваше приложение потенциальным уязвимостям безопасности, таким как атаки с использованием межсайтовых сценариев (XSS).
Avoid: ❌ function MyComponent({ htmlContent }) { return <div dangerouslySetInnerHTML={{ __html: htmlContent }} />; } DO: ✅ import DOMPurify from 'dompurify'; // ... function renderUserContent(content) { const sanitizedContent = DOMPurify.sanitize(content); return { __html: sanitizedContent }; } function ContentDisplay({ content }) { return <div dangerouslySetInnerHTML={renderUserContent(content)} />; }
Политика безопасности контента (CSP)🔒
Внедрите CSP, чтобы контролировать, какие сценарии и ресурсы можно загружать и выполнять на вашей веб-странице. Это предотвращает запуск неавторизованных сценариев.
Когда вы создаете приложение React JS, важно убедиться, что заголовки CSP правильно установлены на сервере.
Как добавить заголовки безопасности в приложение Next.js
const nextConfig = { reactStrictMode: true, swcMinify: true, // Adding policies: async headers() { return [ { source: '/(.*)', headers: [ { key: 'X-Frame-Options', value: 'DENY', }, { key: 'Content-Security-Policy', value: "default-src 'self' script-src 'self' https://www.google-analytics.com; font-src 'self' 'https://fonts.googleapis.com'", }, { key: 'X-Content-Type-Options', value: 'nosniff', }, { key: 'Permissions-Policy', value: "camera=(); battery=(self); geolocation=(); microphone=('https://a-domain.com')", }, { key: 'Referrer-Policy', value: 'origin-when-cross-origin', }, ], }, ]; }, } module.exports = nextConfig
Использование react-helmet
— еще один допустимый подход к добавлению заголовков безопасности в приложение Next.js. Вот правильный способ использования react-helmet
для добавления заголовков безопасности.
Шлем React🎩
- Используйте пакет react-helmet. Он используется в приложениях React JS для управления содержимым раздела HTML head. Это полезно для настройки метаданных, заголовков, стилей и других элементов в разделе заголовка.
DO: ✅ import React from 'react'; import { Helmet } from 'react-helmet'; function MyPage() { return ( <div> <Helmet> <title>My Page Title</title> <meta name="description" content="This is my page's description." /> <link rel="stylesheet" href="path/to/styles.css" /> </Helmet> {/* Other JSX content for your page */} </div> ); } export default MyPage;
- Установите заголовок Content-Security-Policy, используя React-Heled, чтобы обеспечить соблюдение политик безопасности на стороне сервера.
Экспресс-пример:
DO: ✅ const express = require('express'); const helmet = require('helmet'); const { Helmet } = require('react-helmet'); const React = require('react'); const ReactDOMServer = require('react-dom/server'); const app = express(); app.use(helmet()); app.get('/', (req, res) => { const helmetData = Helmet.renderStatic(); // Collect helmet data from your React components const contentSecurityPolicy = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"; // Your CSP rules res.set({ 'Content-Security-Policy': contentSecurityPolicy, ...helmetData.meta.toComponent(), ...helmetData.title.toComponent(), // Add other headers if needed }); const reactApp = ReactDOMServer.renderToString(React.createElement(YourAppComponent)); res.send(` <!DOCTYPE html> <html> <head> ${helmetData.title.toString()} ${helmetData.meta.toString()} </head> <body> <div id="root">${reactApp}</div> </body> </html> `); }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
Пример Next.js
DO: ✅ import { NextSecureHeadersMiddleware } from 'next-secure-headers'; const securityHeaders = [ { key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';", }, // Add other headers if needed ]; export default NextSecureHeadersMiddleware({ headers: securityHeaders, });
Кроме того, вам следует избегать использования небезопасных методов, таких как встроенные обработчики событий или встроенные стили, поскольку они могут противоречить вашей политике CSP.
Например:
Вместо использования <button onclick="doSomething()">Click me</button>
вам следует использовать обработку событий React, например:
Avoid: ❌ <button onclick="doSomething()">Click me</button> DO: ✅ <button onClick={doSomething}>Click me</button>
Аналогично, избегайте использования встроенных стилей и вместо этого используйте классы CSS.
Avoid: ❌ <div style="color: red;">Hello</div> DO: ✅ <div className="text-color">Hello</div>
Проверка и очистка ввода🧹
- Проверяйте и очищайте входные данные на стороне клиента, чтобы предотвратить атаки путем внедрения.
— Используйте атрибуты HTML, такие какrequired, min, max, type, etc.
, для обеспечения базовой проверки входных данных.
DO: ✅ function MyForm() { const handleSubmit = (event) => { event.preventDefault(); // Validate inputs here }; return ( <form onSubmit={handleSubmit}> <input type="text" required pattern="[A-Za-z]+" /> <button type="submit">Submit</button> </form> ); } Avoid: ❌ <form action="/register" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="username" pattern="[A-Za-z0-9]+" required> <label for="password">Password:</label> <input type="password" id="password" name="password" pattern=".{8,}" required> <button type="submit">Register</button> </form>
— Очистка ввода
Вы можете использовать сторонние библиотеки, чтобы упростить проверку и улучшить взаимодействие с пользователем. Такие библиотеки, как react-hook-form
, Formik
и yup
, предоставляют инструменты для управления формами, проверки и обработки ошибок:
DO: ✅ import { useForm } from 'react-hook-form'; import * as yup from 'yup'; const schema = yup.object().shape({ username: yup.string().required(), email: yup.string().email().required(), }); function MyForm() { const { register, handleSubmit, errors } = useForm({ validationSchema: schema, }); const onSubmit = (data) => { // Handle form submission }; return ( <form onSubmit={handleSubmit(onSubmit)}> <input name="username" ref={register} /> <input name="email" ref={register} /> <button type="submit">Submit</button> {errors.username && <p>Username is required</p>} {errors.email && <p>Invalid email</p>} </form> ); }
Использование HTTPS 🔒
- Обслуживайте свое приложение React по протоколу HTTPS, чтобы обеспечить зашифрованную связь между клиентом и сервером.
Безопасная аутентификация и авторизация🔐
- Внедрите надлежащие механизмы аутентификации и авторизации, такие как OAuth, JWT или cookie, и обеспечьте безопасное хранение токенов аутентификации.
- Авторизуйте пользователей на основе ролей и разрешений, чтобы ограничить доступ к конфиденциальной информации.
- Используйте установленную аутентификацию, например Next.js Auth,
passport
для безопасной обработки потоков аутентификации. Эти библиотеки были разработаны для решения общих проблем безопасности.
Безопасное управление состоянием🔒
Используйте такие библиотеки, как Redux и React Content API, для управления состоянием приложения.
TСторонние библиотеки и компоненты📚
- Используйте только проверенные и хорошо поддерживаемые сторонние библиотеки и компоненты.
- Регулярно просматривайте и обновляйте зависимости, чтобы избежать известных уязвимостей.
Защитите конфиденциальные данные с помощью шифрования 🔑
Убедитесь, что конфиденциальные данные, такие как пароли пользователей, ключи API и токены, надежно зашифрованы. Используйте библиотеки шифрования, такие как bcrypt или crypto js, чтобы защитить конфиденциальную информацию и смягчить последствия утечки данных.
DO: ✅ // Client Side - BcryptJS import React from 'react'; import bcrypt from 'bcryptjs'; function RegistrationForm() { const handleSubmit = async (event) => { event.preventDefault(); const plainPassword = event.target.password.value; const hashedPassword = await bcrypt.hash(plainPassword, 10); // Send hashedPassword to the server for storage // ... }; return ( <form onSubmit={handleSubmit}> <input type="password" name="password" placeholder="Password" /> <button type="submit">Register</button> </form> ); } export default RegistrationForm; // Client Side - CryptoJS import React from 'react'; import CryptoJS from 'crypto-js'; function EncryptDecryptExample() { const plaintext = 'sensitive_data'; const secretKey = 'super_secret_key'; // Encrypt data const ciphertext = CryptoJS.AES.encrypt(plaintext, secretKey).toString(); // Decrypt data const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey); const decryptedData = bytes.toString(CryptoJS.enc.Utf8); return ( <div> <p>Encrypted: {ciphertext}</p> <p>Decrypted: {decryptedData}</p> </div> ); } export default EncryptDecryptExample;
Статический анализ кода📝
Используйте такие инструменты, как ESLint и Prettier, чтобы обеспечить соблюдение стандартов кодирования и выявить потенциальные уязвимости безопасности на этапе разработки.
Обработка ошибок 🔧
Обрабатывайте ошибки корректно, не раскрывая конфиденциальную информацию пользователям.
Спасибо, что дочитали до конца. Пожалуйста, следите за автором и этой публикацией. Посетите Stackademic, чтобы узнать больше о том, как мы демократизируем бесплатное образование в области программирования во всем мире.
Если вам понравилась моя работа, пожалуйста:
Следуйте за мной и подпишитесь
- "Подписывайтесь на меня"
- "Подписаться"
- ЛинкедИн
1. Пожертвовать 💕
Оплата на сайте Revolut или используйте QR-код выше.
Ваше пожертвование подпитает мое стремление продолжать создавать значимую работу. Спасибо! 🦁💚