Рекомендации по управлению токеном аутентификации

Я пишу клиент REST в Java с использованием HttpCLient, API REST, к которому я обращаюсь, требует токена аутентификации для каждого действия REST. Этот токен действителен в течение 24 часов.

То, как я сейчас обрабатываю это, вызывает метод "getAuth()" каждый раз, когда мне нужно сделать вызов REST, который кажется накладным на сервере auth.

Как я могу удобно хранить этот токен и управлять его жизненным циклом? Существуют ли какие-либо задокументированные рекомендации?

Я подумал о следующем решении

public class MySession {
    String user;
    String pass;
    public MySession(String user, String pass) {
        this.user = user;
        this.pass = pass;
    }

    public getAuth() {
        //user user, pass to get auth token 
    }
}

а затем передать объект сеанса любому классу, который содержит токен. Если токен истек, просто вызовите этот метод еще раз

Ответ 1

Я предлагаю вам использовать следующий сценарий:

1) Сначала вызовите auth(username, password) rest api, чтобы получить токен auth. Если данные учетные данные в порядке, то просто отправьте файл cookie auth клиенту с кодом ответа HTTP 200.

2) Затем вы можете вызвать protected rest apis. Вам необходимо каждый раз отправлять auth cookie с вашим запросом.

3) Сервлет-фильтр (или что-то подобное) проверяет каждый входящий запрос и проверяет токен. Если токен действителен, запрос переходит к следующему методу, если вам не нужно генерировать ответ http 401/403.

Я предлагаю вам не писать собственный уровень аутентификации. Вместо установки и использования существующего. Я предлагаю вам OpenAM. Это превосходная система управления доступом с открытым исходным кодом.

Я также предлагаю вам не открывать сеанс на стороне сервера для целей аутентификации. Если у вас 10 клиентов, то 10 сеансов должны управляться сервером. Это не большая проблема. Но если у вас есть 100 или 1000 или миллионы разных клиентов, чем вам нужно больше памяти для хранения сеансов на сервере.

Ответ 2

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

При выполнении авторизации вы получите access_token с истечением срока действия и в зависимости от типа гранта, который вы запрашиваете (учетные данные клиента, код авторизации, неявный, владелец ресурса), refresh_token.

Клиент должен хранить access_token и истечение срока действия. Обновление refresh_token, если оно выпущено, должно храниться в секрете (остерегайтесь использовать правильный грант для вашего случая использования).

В последующих вызовах ваш клиент не должен запрашивать новые токены для каждого вызова, он должен использовать сохраненный access_token.

Как только API начнет возвращаться 401 Unauthorized, срок действия access_token, вероятно, истек. Ваш клиент должен попытаться обновить access_token с помощью refresh_token, если у вас есть.

Если у вас нет refresh_token или запрос обновления также не удался, поскольку refresh_token больше недействителен, вы можете выполнить новый поток авторизации.

Вы можете использовать время истечения срока действия, чтобы узнать, когда получить новый access_token либо через обновление, либо через новый полный поток авторизации. Это позволит избежать 401 Unauthorized. В любом случае у вашего клиента должна быть политика возврата, когда этот ответ получен после использования действительного access_token для некоторых вызовов.

Ответ 3

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

Я бы не рекомендовал использовать Session в вашем случае, а скорее хранить токен в cookie на клиенте.

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

Как упоминал также @Cássio Mazzochi Molin, вы можете использовать кеш в памяти для хранения данных и токенов, специфичных для пользователя. Это уменьшит количество обращений к базе данных, а также позволит вам масштабировать приложение при необходимости.

Ответ 4

Стандарт de facto не реализует ваше собственное решение (основное правило в безопасности: не реализует ваши собственные вещи!), но используйте де-факто стандартное решение, а именно JSON Web Tokens.

Документация на сайте, но основная идея заключается в том, что вам нужно сохранить только одно значение (секретный ключ сервера), а затем вы можете проверить все претензии, выпущенные первоначально сервером (который в вашем случае содержит время истечения срока действия).

Ответ 5

Для краткости я предполагаю, что вы вызываете конечную точку, которую вы не можете изменить. Как вы должны реализовать, будет сильно зависеть от того, является ли токен приложением или пользователем (один токен для всех пользователей в экземпляре общего приложения или один токен на пользователя).

Если это один токен для всего приложения:

  • Храните его в памяти вместе с временной меткой времени (или, как альтернатива, уловите ошибку с истекшим сроком действия, запросите новый токен и повторите первоначальный запрос), обновите его, если он не существует/истек.
  • Если вы беспокоитесь о повторном запросе маркеров API после перезапуска приложения, также сохраните его в базе данных и загрузите при запуске, если он существует

Если это один токен для пользователя:

  • Храните его в своем пользовательском сеансе, именно для того, для каких сеансов используются, если вы используете пользователей, то у них будет сеанс, а накладные расходы уже есть.
  • Если вы не хотите повторно запрашивать токен каждый раз, когда они регистрируют свой текущий токен в БД и загружают его в свой сеанс при входе в систему

Ответ 6

Вы можете создать менеджер и сохранить auth-cookie во время входа в поток локально, как показано ниже. Вы можете получить файл cookie с getAuth() до тех пор, пока он не будет проживать.

public class Manager {
    private static final ThreadLocal<String> SECURITY_CONTEXT = new ThreadLocal<>();

    public static void setAuth(String auth) {
        SECURITY_CONTEXT.set(auth);
    }

    public static String getAuth() {
        return SECURITY_CONTEXT.get();
    }

    public static void clear(){
        SECURITY_CONTEXT.remove();
    }
}

Ответ 7

Вы должны использовать JsonWebToken (кратко JWT) для такого рода вещей. JWT имеет поддержку для установки даты истечения срока действия. Существует множество библиотек для использования этого метода, и вы можете читать здесь

Существуют версии java-версий currenlty и все они могут проверить, действительно ли токен (проверка проверки) введите описание изображения здесь

Ответ 8

Итак, если я правильно понимаю, вы используете один и тот же токен для всех своих запросов (это означает, что пока ваше приложение работает и вы обновляете токены, вы должны быть в порядке. Я буквально имел ту же проблему и вот как я это разрешил. У меня есть одноэлементный класс, который инициализируется в начале приложения за один раз и обновляет токен, когда он недействителен. Я использую С#, Asp.NET MVC5 и AutoFac для DI, но я Конечно, вы можете сделать то же самое с Java и Spring.

Обновление свойства одноэлемента с безопасностью потока

Ответ 9

Использовать токены json для обмена информацией между двумя клиентами. Токен будет действовать только в течение 24 часов, после этого все последующие вызовы в заголовке будут отклонены.

Ответ 10

  • Auth Token для каждого запроса является правильным подходом, рассмотрите масштабирование сервера auth для проблемы с производительностью.
  • При первой успешной аутентификации (имя пользователя и пароль) создайте приватную партию ключей. Храните закрытый ключ как токен безопасности сеанса (SST) и отправьте открытому ключу как Клиентский ключ общественной безопасности (PSCK) для клиента
  • Во всех запросах, кроме входа (аутентификации), клиент отправляет PSCK для защиты кражи имени пользователя и пароля, а сервер может проверять PSCK на срок до истечения регулярного промежутка времени, экономя время обработки.
  • Если система имеет проблемы с производительностью на стороне аутентификации, настройте отдельный сервер auth с масштабируемостью.
  • Нет маркера или пароля для кэширования, обмена незашифрованных и отправки внешней зоны безопасности. Не публикуйте параметры URL.