Получение защищенных изображений AWS S3 в React Native
Получение защищенных изображений AWS S3 в React Native

Введение

В современных приложениях, особенно работающих с мультимедийным контентом, эффективное управление такими ресурсами, как изображения, имеет решающее значение для плавного пользовательского опыта. Amazon Simple Storage Service (S3) является популярным выбором.

Один из распространенных подходов к обеспечению безопасного доступа к ресурсам — использование предварительно подписанных URL-адресов. Эти URL-адреса предоставляют временный доступ к определенным ресурсам в корзине S3, позволяя контролировать доступ без ущерба для безопасности.

Хотя обычно предварительно подписанные URL-адреса генерируются на серверной стороне и предоставляются на фронтенд, бывают ситуации, когда необходимо обрабатывать предварительно подписанные URL-адреса непосредственно на фронтенде приложения React Native. Это может быть связано с различными причинами, такими как динамический контент, управление доступом для конкретных пользователей или необходимость тонкого управления доступом.

В этом руководстве мы шаг за шагом рассмотрим процесс предварительной подписи URL-адресов AWS S3 в приложении React Native.

Хотя документация AWS предоставляет исчерпывающие инструкции по предварительно подписанным URL-адресам, она может не предлагать конкретных инструкций по интеграции этой функциональности в приложение React Native. Документация AWS по предварительно подписанным URL-адресам

Давайте углубимся в то, как это сделать в нашем приложении React Native.

Предварительные условия

  • Вам нужна учетная запись AWS для доступа к сервисам Amazon S3. Если у вас ее нет, вы можете зарегистрироваться здесь.

  • Необходимы Ключи доступа и секретные ключи для аутентификации запросов к сервисам AWS, включая S3. Вы можете получить эти учетные данные, создав пользователя IAM с соответствующими разрешениями в консоли управления AWS. Убедитесь, что вы храните эти учетные данные безопасно и избегайте их раскрытия в общедоступных репозиториях или клиентском коде.

  • Необходим Node.js для установки пакетов и запуска инструментов на базе JavaScript. Убедитесь, что Node.js установлен на вашей машине для разработки. Вы можете скачать и установить Node.js с официального сайта: Загрузки Node.js.

  • Настройте среду проекта React Native на вашей машине, если вы еще этого не сделали. Вы можете следовать официальной документации React Native для инструкций по настройке вашей среды разработки: React Native — Начало работы.

Шаг 1: Настройка AWS SDK

Во-первых, установите пакет aws4-react-native, который предоставляет необходимые инструменты для подписи запросов AWS в приложениях React Native. Кроме того, установите библиотеку react-native-fast-image, которая предоставляет высокопроизводительный и настраиваемый компонент изображения для приложений React Native. Эта библиотека предназначена для быстрого рендеринга изображений и включает такие полезные возможности, как кэширование.

npm install aws4-react-native

npm install react-native-fast-image

Шаг 2: Напишите функцию предварительной подписи

Создайте функцию, которая генерирует предварительно подписанный URL-адрес для заданного объекта S3. Эта функция будет использовать библиотеку aws4 для подписи запроса.

Предположим, что наши изображения имеют следующие URL-адреса:

'https://s3.bucket-name.com/compressed-images/your-image-key.webp';

Где:

"s3.bucket-name.com" — это имя хоста корзины S3

"compressed-images/your-image-key.webp" — остальная часть URL-адреса — путь к изображению

"your-image-key.webp" — это ключ изображения

// helpers/generate-presigned-urls.ts

// Импорт необходимых модулей

var aws4 = require('aws4-react-native');

// Функция для генерации предварительно подписанного URL

export function generatePreSignedUrl(imageUrl, expirationSeconds = 3600) {

  // Извлечение ключа объекта из URL изображения

  const parts = imageUrl.split('/');

  const lastPart = parts[parts.length - 1];

  const path = 'compressed-images/' + lastPart;

  // Определение опций для подписи

  const opts = {

    service: 's3',

    region: 'your-region', // например, eu-west-2

    path: path,

    host: 'your-s3-host', // в нашем случае s3.bucket-name.com

  };

  // Подпись запроса

  aws4.sign(opts, {

    accessKeyId: 'ACCESS_KEY',

    secretAccessKey: 'SECRET_KEY',

  });

  // Возвращение подписанных заголовков

  return {

    Authorization: opts.headers.Authorization,

    X_Amz_Date: opts.headers['X-Amz-Date'],

  };

}

Результат будет примерно таким:

const imageUrl = 'https://s3.bucket-name.com/compressed-images/your-image-key.webp';

const presignedUrl = generatePreSignedUrl(imageUrl);

console.log("Pre-signed URL:", presignedUrl);

Pre-signed URL: https://s3.REGION.amazonaws.com/s3.bucket-name.com/compressed-images/your-image-key.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ACCESS_KEYaws4_request&X-Amz-Date=20231018T075941Z&X-Amz-Expires=3600&X-Amz-Signature=SIGNATURE-SignedHeaders=host

Шаг 3: Создайте компонент изображения

import React from 'react';

import { ActivityIndicator, ImageStyle, StyleProp, StyleSheet, View } from 'react-native';

import FastImage from 'react-native-fast-image';

import { generatePreSignedUrl } from 'helpers/generate-presigned-url'; // ранее созданная функция для генерации предварительно подписанных URL

interface Props {

  imageURL: string;

  style: StyleProp<ImageStyle>;

  resizeMode: 'contain' | 'cover' | 'stretch';

}

export const AWSS3Image = React.memo((props: Props) => {

  const [isLoading, setIsLoading] = React.useState(true);

  const presignedURL = React.useMemo(() => {

    return generatePreSignedUrl(props.imageURL);

  }, [props.imageURL]);

  const onLoading = () => {

    setIsLoading(false);

  };

  return (

    <FastImage

      source={{

        uri: props.imageURL,

        headers: {

          'X-Amz-Content-Sha256':

            'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // хеш пустой строки, остается неизменным для всех реализаций

          'X-Amz-Date': presignedURL.X_Amz_Date,

          Authorization: presignedURL.Authorization,

        },

      }}

      style={props.style}

      resizeMode={props.resizeMode}

      onLoad={onLoading}>

      {isLoading && (

        <View style={styles.loaderContainer}>

          <ActivityIndicator size="large" />

        </View>

      )}

    </FastImage>

  );

});

const styles = StyleSheet.create({

  loaderContainer: {

    flex: 1,

    justifyContent: 'center',

    alignItems: 'center',

  },

});

Заголовок 'X-Amz-Content-Sha256' со значением 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' связан с SHA-256 хешем пустой строки. Это значение хеша представляет содержимое полезной нагрузки запроса, которое в контексте генерации предварительно подписанных URL-адресов для AWS S3 часто является пустой строкой. Это значение остается постоянным во всех реализациях и важно для поддержания целостности запроса и обеспечения успешной аутентификации с AWS S3.

Шаг 4: Использование

Теперь вы можете использовать компонент AWSS3Image в вашем приложении React Native для безопасного отображения изображений из AWS S3.

import React from 'react';

import { View, ImageStyle, StyleProp } from 'react-native';

import { AWSS3Image } from './path/to/aws-s3-image';

const App = () => {

  return (

    <View>

      <AWSS3Image

        imageURL="https://your-s3-bucket-url/image.jpg"

        style={styles.image}

        resizeMode="cover"

      />

    </View>

  );

};

const styles = {

  image: {

    width: 200,

    height: 200,

  } as StyleProp<ImageStyle>,

};

export default App;

Заключение

В заключение, эта статья предоставила практическое руководство по реализации предварительно подписанных URL-адресов в приложениях React Native для доступа к защищенным ресурсам, хранящимся в AWS S3. Мы рассмотрели процесс программной генерации предварительно подписанных URL-адресов с помощью SDK AWS, а также интеграцию библиотеки react-native-fast-image для эффективного рендеринга изображений. Следуя

этим шагам, разработчики могут безопасно предоставлять временный доступ к определенным ресурсам S3, обеспечивая при этом оптимальную производительность в приложениях React Native.

Комментарии (0)