2013-02-19 2 views
7

Я разрабатываю веб-игру. Как часть игры, вы начинаете с ограниченного набора функций, и вы разблокируете больше их во время игры.Какой код ответа подходит для этой ситуации?

Например, вы разблокируете /fields как часть шага 3 в учебнике. Но что, если вы просто переходите к /fields в адресную строку?

Я пытаюсь решить, какой будет лучший код состояния для ответа.

403 кажется идеальным, так как пользователю запрещено доступ к странице, пока они не разблокируют его.
404 также имеет смысл, поскольку страница технически «не существует» до тех пор, пока она не разблокирована, а также не позволит пользователям определить разницу между страницей, которая не существует, и той, которую они еще не разблокировали.

Но в обоих случаях у некоторых пользователей возникли проблемы с браузером, который просматривает результат 403/404 и не позволяет им получить доступ к странице даже после ее разблокировки, если они полностью не очищают кеш.

Мне интересно, следует ли мне использовать 403 или 404, или использовать неиспользуемый код 4XX, например 442 с пользовательским статусом, или даже в шутку отправить HTTP/1.1 418 I'm A Teapot в ответ на то, быть.

Мне нужна хорошая, прочная причина, по которой один вариант должен использоваться над другими.

+2

Я не знаю правильного ответа, но следующее сообщение содержит несколько интересных аргументов: http://stackoverflow.com/questions/3297048/403-forbidden-vs-401-unauthorized-http-responses – RobJohnson

+1

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

+2

Кстати, '401 Unauthorized' будет плохой идеей, потому что этот код состояния предназначен только для HTTP-аутентификации, и браузеры обрабатывают этот код состояния специально. – nalply

ответ

3

tl; dr409 Conflict - идея, но, возможно, у вас проблемы с кешированием. В этом случае будет работать кеш-бастер для принудительной перезагрузки.

Длинные объяснения

Возможно код 409 Conflict статус будет иметь смысл:

10.4.10 409 Конфликт

Запрос не может быть выполнен из-за конфликта с текущим состоянием ресурса. Этот код разрешен только в ситуациях, когда ожидается, что пользователь сможет разрешить конфликт и повторно отправить запрос. Тело ответа ДОЛЖНО включать достаточную информацию, чтобы пользователь мог распознать источник конфликта. В идеальном случае объект ответа будет содержать достаточную информацию для пользователя или агента пользователя для устранения проблемы; однако это может быть невозможно и не требуется.

Конфликты, скорее всего, возникнут в ответ на запрос PUT. Например, если использовалось управление версиями, а объект PUT включал изменения в ресурс, который конфликтует с теми, которые были сделаны с помощью более раннего (стороннего) запроса, сервер может использовать ответ 409, чтобы указать, что он не может выполнить запрос , В этом случае объект ответа, скорее всего, будет содержать список различий между двумя версиями в формате, определяемом ответом Content-Type.

Это имело бы смысл, поскольку ресурс доступен только после того, как пользователь выполнил учебное пособие. До этого ресурс находится в «недействительном» состоянии. И пользователь может решить этот конфликт, заполнив учебное пособие.

Позже я исследовал случай немного больше, и я обнаружил, что дьявол находится в деталях. Давайте рассмотрим спецификацию для 403 Forbidden и 404 Not Found.

10.4.4 403 Запрещено

Сервер понял запрос, но отказывается выполнять его. Авторизация не поможет, и запрос НЕ ДОЛЖЕН повториться. Если метод запроса не был HEAD, и сервер хочет сообщить, почему запрос не был выполнен, ему ДОЛЖЕН описать причину отказа в сущности. Этот код состояния обычно используется, когда сервер не хочет точно определить, почему запрос был отклонен, или когда другой ответ не применим.

Немаловажным является спецификация, которая «запрос НЕ ДОЛЖЕН быть повторен». Браузер, который никогда не запрашивает страницу 403, может сделать все правильно. Тем не менее, давайте продолжим с 404:

10.4.5 404 Не найдено

Сервер ничего совпадающий с Request-URI не найден. Не указывается, является ли это условие временным или постоянным.

[опущено]

Теперь у нас есть проблема! Почему ваши 404 страницы будут кэшироваться, если спецификация позволяет им быть временными?

Возможно, в настройках кэширования вы настроили неверно для своих 403 и 404 страниц. Если это так, обратитесь к this answer on StackOverflow. Он дает подробный ответ о кешировании 4хх страниц.

Если вы не хотите возиться с кэшированием заголовков, использовать так называемый кэш-попойка и передать системное время как этот (предполагается, что PHP как ваш веб-языка):

<a href="/fields?<?php echo time(); ?>">

Этот производит URL-адреса, такие как /fields?1361948122, увеличиваясь каждую секунду. Это вариант решения, предложенного Маркусом А.

Я предполагаю, что запрос с номером 1361948122 игнорируется вашим ресурсом. Если это не так, передайте кеш-буттер в параметре querystring, например, t=1361948122 и убедитесь, что параметр t не оценивается вашим ресурсом.

2

С точки зрения предполагаемой цели кодов ошибок HTTP, я бы определенно пойти с 403 Forbidden, потому что страница существует (404 выходит), но пользователь запрещено к нему доступ сейчас (и это ограничение не связано с конфликтом ресурсов, например, с одновременной модификацией, но из-за состояния учетной записи пользователя, то есть, по моему мнению, тоже 409). Другим разумным вариантом, основанным на его намеренной цели, могло быть 401, но, как уже отмечалось в его комментарии, этот код запускает некоторые, если не все, браузеры для отображения диалогового окна входа в систему, поскольку это подразумевает, что использование стандартного механизма веб-аутентификации может решить проблему. Таким образом, это определенно не будет вариантом для вас здесь.

Две вещи кажутся немного «misfitting» в описании 403, так что позвольте мне обратиться к ним:

  1. Авторизация не поможет ...: Это говорит только о механизме авторизации внутри HTTP протокол и предназначен для различения 403 с 401.Этот оператор не применяется к какой-либо форме пользовательского авторизации или управления сеансом.
  2. ... запрос НЕ ДОЛЖЕН повториться ...: Запрос должен всегда отображаться в контексте сеанса, поэтому, если контекст сеанса пользователя изменяется (он открывает функцию), а затем он пытается получить доступ к тот же ресурс, то есть другой запрос, т. е. нет никакого нарушения этого предложения.

Конечно, вы также можете определить свой собственный код ошибки, но поскольку он, вероятно, не будет зарезервирован каким-либо официальным способом, нет никакой гарантии, что какой-либо производитель браузеров не намеренно или случайно не использует точно этот код запускает определенное (отладочное) действие. Это маловероятно, но не запрещено.

418 может быть в порядке, тоже. :)

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

Теперь к вашему вопросу кэширования:

Ни один из этих кодов состояния (403, 404, 409, 418) должен триггерных браузер кэшировать страницу против вашей воли больше, чем любой другой. Проблема в том, что многие браузеры просто пытаются кэшировать все, как сумасшедшие, чтобы быть более быстрым. Оперы здесь хуже всего, на мой взгляд. Я много раз вытягивал свои волосы над этими вещами. СЛЕДУЕТ иметь возможность работать со всеми правильными настройками заголовка, но у меня были ситуации, когда либо браузер, либо сервер, либо какой-то промежуточный прокси решили игнорировать их и в любом случае сломать мою страницу.

Единственный надежный способ, который я нашел до сих пор, что абсолютно положительно гарантирует перезагрузку, заключается в добавлении параметра фиктивного запроса, например/fields? T = 29873, где 29873 - это номер, который уникален для каждого запроса, который вы делаете в любых возможных временных масштабах. На сервере, конечно, вы можете просто игнорировать этот параметр. Обратите внимание, что недостаточно просто начать с 1, когда ваш пользователь сначала откроет вашу страницу, а затем подсчитает следующие запросы, так как браузеры могут хранить кеш во всех перезагрузках страниц.

Я делаю веб-разработки в Java (как сервера и на стороне клиента с помощью GWT), и я использую этот код для создания фиктивных «номера»:

private static final char[] base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.".toCharArray(); 
private static int tagIndex = 0; 

/** 
* Generates a unique 6-character tag string that is guaranteed to not repeat 
* for about 400 days, if this function is, on average, not called more often 
* than twice every millisecond. 
* 
* @return the tag string 
*/ 
public static String nowTag() { 
    int tag = (int) ((System.currentTimeMillis() >>> 5)); // adjust 
    char[] result = new char[6]; 
    result[5] = base64chars[(tagIndex++) & 63]; 
    result[4] = base64chars[tag & 63]; 
    tag >>>= 6; 
    result[3] = base64chars[tag & 63]; 
    tag >>>= 6; 
    result[2] = base64chars[tag & 63]; 
    tag >>>= 6; 
    result[1] = base64chars[tag & 63]; 
    tag >>>= 6; 
    result[0] = base64chars[tag & 63]; 
    return new String(result); 
} 

Он использует часы системы в сочетании с счетчик, который сможет обеспечить до двух гарантированных уникальных значений каждые миллисекунды. Вам может не понадобиться эта скорость, поэтому вы можете свободно изменять >>> 5, который я обозначил «настраивать», чтобы он соответствовал вашим потребностям. Если вы увеличите его на 1, ваша ставка снизится в два раза, а время вашей уникальности удвоится. Так, например, если вы положили >>> 8, вы можете генерировать около 1 значения каждые 4 мс, а значения не должны повторяться в течение 3200 дней. Конечно, эта гарантия, что значения не будут повторяться, исчезнет, ​​если пользователь столкнутся с системными часами. Но так как эти значения не генерируются последовательно, все равно очень маловероятно, что вы нажмете один и тот же номер дважды. Код генерирует 6-символьную текстовую строку (base64), а не десятичное число, чтобы максимально сократить URL-адреса.

Надеюсь, это поможет.:)

0

Я чувствую, что нет необходимости бросить код ошибки, несмотря на просто отобразить сообщение как

Вы должны быть уровень XX доступа к этой странице или что-то смешное, как Come назад, когда вы вырастите

с кодом 200-ОК, поэтому проблема с кешем не будет достигнута, и цель также будет достигнута.

Смежные вопросы