Какой код состояния http должен использоваться, чтобы сообщить клиенту, что время сеанса истекло?

80

На веб-странице он использует диспетчер соединений / источник данных YUI для отправки запросов AJAX на сервер, если сеанс (который содержит информацию о том, прошел ли пользователь аутентификацию) уже истек, те ответы ajax, которые могут быть просмотрены только аутентифицированными пользователи должны возвращать код состояния http, сообщая клиенту, что время сеанса уже истекло, затем клиент либо просто перенаправляет его на страницу входа в систему, либо спрашивает его, хочет ли он продлить сеанс.

Мой вопрос в том, что в этой ситуации какой код состояния http наиболее подходит, чтобы сообщить клиенту, что время сеанса истекло?

Список кодов состояния HTTP из вики

бобо
источник
Вы хотите предупредить пользователя о том, что сеанс скоро истечет, чтобы пользователь мог что-то сделать для его возобновления? Если это так, это должно обрабатываться таймером в JavaScript, который срабатывает до истечения времени ожидания сеанса на сервере. К тому времени, как код состояния будет отправлен сервером, срок его действия уже истек. Также потребуется таймер, если вы автоматически перенаправляете их на другую страницу, если они оставляли страницу незанятой.
Джейсон
8
Да 418 конечно! Короткий и крепкий ...
Тим Пост
Ваадин использует 410 Gone, но, поскольку он кешируется браузером, я бы не рекомендовал его
sreg

Ответы:

66

Лучшее, что я могу предложить, - это код состояния HTTP 401 с заголовком WWW-Authenticate.

Проблема с запросами 403 - это RFC 2616. говорится: «Авторизация не поможет, и запрос НЕ ДОЛЖЕН повторяться». (т.е. не имеет значения, аутентифицированы вы или нет, вы никогда не получите доступ к этому ресурсу).

Проблема с запросом 401 заключается в том, что в нем говорится, что они «ДОЛЖНЫ включать поле заголовка WWW-Authenticate». Как кто-то заметил, использование настраиваемого значения в заголовке WWW-Authenticate не является нарушением спецификации.

Я не вижу причин в RFC 2617, почему статус HTTP 401 в сочетании с настраиваемым заголовком WWW-Authenticate вроде этого не подходит:

WWW-Authenticate: MyAuthScheme realm="http://example.com"

Спецификация oAuth на самом деле, кажется, делает именно это, поскольку они рекомендуют это (хотя, на мой взгляд, они имеют странную интерпретацию RFC):

WWW-Authenticate: OAuth realm="http://server.example.com/"

Это не выглядит специально САНКЦИОННЫМ RFC, но я на самом деле не вижу, что это запрещено им (похоже, это не противоречит каким-либо условиям ДОЛЖЕН или НЕ ДОЛЖЕН, ДОЛЖЕН или НЕ ДОЛЖЕН).

Я бы хотел, чтобы был более конкретный код состояния HTTP для тайм-аутов и таких вещей, как недействительные токены CSRF, чтобы это было яснее.

Иэн Коллинз
источник
34

Я бы рекомендовал HTTP 401.

В то время как 403 в основном говорит: «Тебе не разрешено, уходи и не возвращайся», 401 говорит: «Мы не знаем, разрешено тебе или нет, потому что ты не принес свой документ. возьми и попробуй еще раз. "

Сравните определения Википедии :

HTTP 403 - запрос был законным, но сервер отказывается отвечать на него.

HTTP 401 - аналогичен 403 Forbidden, но специально для использования, когда аутентификация возможна, но не удалась или еще не была предоставлена.

Джонатон Хилл
источник
3
401 предназначен для аутентификации HTTP . RFC 2616 говорит response MUST include a WWW-Authenticate header field. Поэтому неправильно отправлять этот код без поля заголовка WWW-Authenticate .
toxalot
19

Насчет 419 - нестандартно, но описание в Википедии вроде подходит:

419 Тайм-аут аутентификации

Не являющийся частью стандарта HTTP, 419 Authentication Timeout означает, что срок действия ранее действующей аутентификации истек. Он используется как альтернатива 401 Unauthorized, чтобы отличать от других аутентифицированных клиентов, которым отказано в доступе к определенным ресурсам сервера.

Джон Райхерт
источник
14
Есть идеи, откуда это (кроме Википедии)? Если этого нет в официальном RFC, кто это определил?
анаксимандр
5
Кажется, он также удален с той страницы вики
Салем Уердани
Это не является частью спецификации и не доступно в Java HttpServletResponse@John, если вы знаете какой-либо другой надежный источник, лучше ссылаться на него.
Vishrant
Кажется, я использую только в PHP Laravel
TroySteven
12

Я считаю, что соответствующий код будет 403 / Запрещено. Нет ничего, что напрямую связано с сессиями.

Джейсон
источник
1
Абсолютно правильный ответ. Поскольку время сеанса истекло, запрос запрещен, поэтому это лучший выбор.
marcc
3
403 говорит клиенту (в основном): «Не делайте этого снова, если вы не измените свой запрос», но если сеанс был установлен, никаких изменений не потребуется. Кроме того, в большинстве случаев вы не можете ничего сделать с (текущим) запросом на восстановление сеанса.
Тим Пост
1
Точно! Я думаю, что 401 было бы лучше, но для этого требуется HTTP-аутентификация. Я думаю, это требует нового статуса по линиям 401 + 303 (так что, очевидно, 704), что означает «Не авторизован, см. Другое, чтобы получить авторизацию». В дополнение к тому, что это более семантически правильно, это также может быть HTTP-решение для перенаправления трамплина, в основном «иди сюда, затем, когда ты вернешься, мы попробуем это снова», чтобы страница входа могла быть агностической в ​​отношении пункт назначения.
Энтони
5
Я не могу согласиться с этим, RFC 2616 прямо заявляет, что запросы, которые приводят к ответу 403, «НЕ ДОЛЖНЫ повторяться» клиентом и что «авторизация не поможет».
Iain Collins
5
authorization will not help- Я так понимаю, HTTP-аутентификация не поможет. Что правильно. Отправка заголовка авторизации ничего не изменит. Ни 401, ни 403 не идеальны, но я думаю, что 403 лучше, чем 401. 401 неверно для тайм-аута сеанса, потому что RFC 2616 явно указывает client MAY repeat the request with a suitable Authorization header field. Но в этом случае клиенту НЕ СЛЕДУЕТ повторять запрос (по крайней мере, без промежуточного шага). К сожалению, мы не можем передать последнюю часть с помощью кода состояния.
toxalot 07
11

Правда в том, что стандартного кода состояния HTTP для тайм-аута сеанса не существует. Сеансы реализуются на уровне приложений, а не на транспортном уровне HTTP.

Существует собственный код состояния, который Microsoft использует для тайм-аута сеанса: 599, или просто создайте свой собственный код состояния в диапазоне 5xx.

Из вики-страницы с кодами состояния:

599 Ошибка тайм-аута сетевого подключения (Неизвестно) Этот код состояния не указан ни в каких RFC, но используется прокси-серверами Microsoft Corp. HTTP для сигнализации о тайм-ауте сетевого подключения за прокси-сервером для клиента перед прокси.

Я использую настраиваемый код состояния 599 для тайм-аута сеанса, а затем проверяю его в ответе AJAX.

Дермот Доэрти
источник
3
Тайм-аут сетевого подключения сильно отличается от тайм-аута сеанса. Если вы собираетесь использовать код из расширения Microsoft, почему бы не использовать 440 Login Timeout (Microsoft)в соответствии с ответом Faisal Mq
toxalot
Страница Википедии о 599 была неправильной и не имела цитирования. По-видимому, раньше говорилось, что прокси-серверы Microsoft поднимают 599 при таймауте сети, но я также не мог найти никаких доказательств этого.
Гарет Дэвидсон,
11

Согласно ссылке на Википедию кодов статуса Http, предоставленной выше Bobo:

440 Login Timeout (Microsoft)

    A Microsoft extension. Indicates that your session has expired.
Faisal Mq
источник
Обратите внимание, что apache может преобразовать этот статус возврата в 500, как это сделал мой - stackoverflow.com/questions/17735514/…
commonpike
Мне нравится это решение для сред ASP.NET.
TroySteven
9

Когда вы публикуете ссылку, в этой ссылке я обнаружил этот код состояния HTTP 440 . вы можете использовать код состояния 440 HTTP для истекшего сеанса.

440 Время ожидания входа в систему

 The client's session has expired and must log in again.

401 Unauthorized мы можем использовать, когда учетные данные пользователя неверны. или токен аутентификации, переданный в заголовке, недействителен.

403 Запрещено, мы можем использовать это, когда у пользователя нет определенного разрешения для запрашиваемого ресурса.

Так что, на мой взгляд, мы должны использовать 440 Login Time-out .

Винай Пандья
источник
2

Технически принятый ответ, конечно, правильный: если вы уже точно знаете, что собираетесь не выполнить запрос, и спрашиваете, какой код ошибки возвращать, тогда HTTP 401 «Неавторизованный (не прошедший проверку подлинности)» является подходящим, чтобы запросить повторную аутентификацию.

Но прежде всего спросите себя: следует ли отклонять запрос?

Учтите, что пользователь может просто посещать общедоступную страницу вашего веб-сайта, и в этом случае вы собираетесь шлепнуть его по лицу с надписью «Неавторизовано!» сообщение и требуя от них повторной аутентификации, чтобы увидеть страницу, которую они обычно могли бы видеть без аутентификации. Это не круто.

Мой совет - игнорировать тот факт, что токен сеанса неизвестен, и просто приступить к созданию нового токена сеанса и создать для него новый сеанс. Первоначальное состояние сеанса, конечно же, будет «еще не аутентифицировано», поэтому, если пользователь пытается получить доступ к непубличной странице, то страница будет следить за тем, чтобы он получил HTTP 401 «Неавторизовано (не аутентифицировано). "и должны пройти аутентификацию. Но если пользователь попадает на публичную страницу, он ничего не заметит.

Майк Накис
источник
0

Я бы использовал ответ перенаправления 302 с заголовком «Location», указывающим путь к ресурсу, например «/ auth-required»

Клиент может направить путь к ресурсу в модальное окно с помощью формы входа / пароля, избегая перехода пользователя на другую страницу.

Pinei
источник
-3

Для запросов, отличных от Ajax, я использую перенаправление 302.

Для запросов Ajax я использую 200 для известных ошибок. Таким образом я могу воспользоваться объектом данных. Я считаю, что с объектом данных легче работать, чем разбирать jqXHR для получения информации. И тогда мне не нужно беспокоиться о том, какой код состояния HTTP попытаться переназначить для моей ситуации.

Пример jQuery:

$.ajax({
    //send data to server
})
.done(function(data, textStatus, jqXHR) {
    if (data.success) {
        //then process return data
    }
    else {
        //get error type or message from data object
        //could use custom error codes
    }
})
.fail(function(jqXHR, textStatus, errorThrown) {
    //handle unknown errors
});
токсалот
источник
6
Нежелание анализировать ответ не является хорошей причиной отклоняться от спецификации HTTP, особенно когда вы можете просто JSON.parse (responseText).
Дэвид Нельсон
Я не думаю, что использование кода ответа 200 отклоняется от спецификации HTTP в этом случае, потому что запрос был технически успешным на транспортном уровне. Для меня тайм-ауты сеанса похожи на ошибки формы, когда я возвращаю удобное сообщение об ошибке. Разногласия, выраженные в ответах на этот вопрос, ясно указывают на то, что спецификация HTTP не предоставляет принятый в отрасли код ответа для тайм-аутов сеанса. Как можно отклониться от несуществующей спецификации?
toxalot
-4

Код 408. "Тайм-аут запроса" кажется идеальным - RFC 2616 объясняет, что это означает

Клиент не отправил запрос в течение времени, которое сервер был готов ждать.

т.е. именно «тайм-аут», как вам и нужно!

Алекс Мартелли
источник
4
Но взгляните на остальную часть определения: «Клиент может повторить запрос без изменений в любое время». «Без модификаций» означало бы, что новый сеанс можно было бы создать, просто перезагрузив / обновив запрос. В большинстве случаев, когда используется аутентификация, пользователю необходимо сначала войти в систему.
Эй Джей.
@AJ, конечно, повторный запрос может привести к вызову аутентификации (код HTTP 401) - в спецификациях HTTP не видно ничего, запрещающего это , вы можете указать на что-нибудь?
Алекс Мартелли,
5
408 сообщает клиенту, что они должны просто попробовать повторно отправить запрос как есть, что, очевидно, не сработает, если время сеанса истекло.
Тим Пост
4
408 - это тайм-аут «запроса», а не тайм-аут сеанса. Это означает, что розетка была установлена, но работала слишком долго. Этот сайт хорошо объясняет это: checkupdown.com/status/E408.html
Брэд Купит,