Защита токенов JWT от злоумышленников

Я использую JWT в приложении веб-API ASP.NET Core. Для JWT мне нужен секрет, который я сейчас храню в appsettings.json. Это выглядит так:

"Jwt": {
    "Secret": "cB7lN2sz3H9wI5pAJ8fgkLzV0Q4yxXMiRSO6rTKP1tE7mdjFZCpvWGuoDbhYaeqJnMVwiX5UFz4t8NYsQBoL3rlc20PGfMkj1HvT9pqRbDdOEJZmKaU6gSyWbVx8CnI7T0xywZ2mLI4pk3A9vgHeD5PoFN8jQK1X6sruYRhO0eWtxM3BVzZ9nLD4yfpA7qlUki2Sc6mHJ5XboGrQCVwIwxa9tgPB2sKjRyuM1ZvF7Ylnzhe4H8qo3k"
},

Потенциальный злоумышленник, получивший доступ к моему серверу, теперь может прочитать этот секрет из моего appsettings.json. Если злоумышленник теперь владеет этим секретом, он может создать любые токены JWT для моего приложения.

Чтобы решить эту проблему, я бы теперь использовал шаблон Singleton. Для этого я бы сначала сгенерировал статический класс, имеющий метод генерации случайных строк.

Это будет выглядеть так:

using System.Text;

namespace MyApp.Utils
{
    public class RandomStringGenerator
    {
        private static readonly char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
        private static readonly Random random = new Random();

        public static string Generate(int length)
        {
            var stringBuilder = new StringBuilder(length);

            for (int i = 0; i < length; i++)
            {
                var randomIndex = random.Next(chars.Length);
                stringBuilder.Append(chars[randomIndex]);
            }

            return stringBuilder.ToString();
        }
    }
}

Тогда мне нужен JWTSecretProvider (синглтон). Это будет выглядеть так:

namespace MyApp.Utils
{
    sealed class JWTSecretProvider
    {
        private static string _secret = null!;
        private static JWTSecretProvider _instance;
        private static readonly object _lock = new object();

        private JWTSecretProvider()
        {
            _secret = RandomStringGenerator.Generate(200);
        }

        public static JWTSecretProvider Instance()
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new JWTSecretProvider();
                    }
                }
            }
            return _instance;
        }

        public string GetSecret()
        {
            return _secret;
        }
    }
}

Если мне теперь понадобится доступ к секрету JWT, например. при запуске сервера или когда клиент запрашивает токен JWT после аутентификации, я могу получить к нему доступ следующим образом:

JWTSecretProvider.Instance().GetSecret()

Что вы думаете об этом подходе?

Вы тут путаете терминологию. В вашем appsettings есть не JWT, а ключ, используемый в процессе генерации JWT. Конфиденциальная информация никогда не должна храниться в appsettings. Вместо этого рассмотрите что-то вроде Azure Key Vault или какую-либо альтернативу.

Peppermintology 30.06.2024 18:27

Вы можете хранить их в переменных среды. Переменные среды позволяют избежать хранения секретов приложения в коде или локальных файлах конфигурации, а для доступа к переменным среды требуются более высокие разрешения, чем для чтения файлов. Learn.microsoft.com/en-us/aspnet/core/security/….

Yuning Duan 02.07.2024 09:29

Однако следует отметить, что переменные среды обычно хранятся в незашифрованном виде. Если компьютер или процесс скомпрометированы, недоверенные стороны могут получить доступ к переменным среды. Возможно, вам придется принять дополнительные меры для предотвращения раскрытия секретов пользователей.

Yuning Duan 02.07.2024 09:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Просто чтобы прояснить несколько моментов, вы сказали:

Если злоумышленник теперь владеет этим токеном, он может создать любые токены JWT для моего приложения.

Это не совсем так. Прежде всего, JWT уже зашифрован, поэтому злоумышленник не сможет выяснить, что находится внутри. Даже если злоумышленник сможет выяснить, где, например, находится раздел claims, любая попытка изменить его не сработает. Это связано с тем, что JWT содержит в себе контрольную сумму, гарантирующую, что он не был подделан. Таким образом, злоумышленник не сможет получить доступ после взлома JWT, поскольку сервер обнаружит, что новая контрольная сумма не соответствует значению, содержащемуся в JWT.

Думаю, здесь нужно кое-что объяснить. В JWT есть два токена. Один токен — случайно сгенерированная строка — находится в настройках приложения. Меня беспокоит этот вопрос. Не токен JWT, который получает клиент. Мне нужен токен в настройках приложения, чтобы генерировать токены для клиентов. Как правильно защитить токен в настройках приложения? Подходит ли мой подход для этого?

Ali 30.06.2024 17:43

Итак, по сути, вы спрашиваете, хранить ли секрет Het JWT в appsettings.json или другим способом?

WiseDev 30.06.2024 23:19

@WiseDev да. Мой подход хорош? Я храню секрет JWT в одноэлементном классе и создаю секрет при запуске сервера. Это хороший подход?

Ali 01.07.2024 09:22

«Достаточно хорошо», если вы уверены, что он там будет в безопасности. Но, конечно, всегда можно улучшить хранение секретов, используя такие методы, как Хранилища и т. д.

WiseDev 16.07.2024 06:11
Ответ принят как подходящий

Поскольку секрет JWT — это секрет, который необходимо особо охранять, я пришел к выводу, что мой подход неправильный. Как уже упоминалось в своем комментарии Peppermintology, рекомендуемым решением является хранение секрета JWT в Azure Key Vault или чем-то подобном. Я рассмотрю это решение для моей проблемы. Спасибо Peppermintology и всем остальным, кто здесь помог.

Другие вопросы по теме