就 HTTP 错误代码的预期目的而言,我肯定会选择403 Forbidden
,因为该页面确实存在(404 已退出),但用户暂时被禁止访问它(并且此限制不是由于资源冲突造成的) ,就像并发修改一样,但是由于用户的帐户状态,我认为 409 也是如此)。基于其预期目的的另一个明智的选择可能是 401,但正如 nalply 在他的评论中已经指出的那样,此代码会触发一些(如果不是全部)浏览器显示登录对话框,因为这意味着使用标准的 web 身份验证机制可以解决问题。所以,这里绝对不是你的选择。
在 403 的描述中,有两件事似乎有点“不合适”,所以让我来解决它们:
- 授权无济于事……:这里只讲HTTP协议内部的授权机制,是为了区分403和401。此声明不适用于任何形式的自定义授权或会话状态管理。
- ...不应该重复请求...:必须始终在会话上下文中看到请求,因此如果用户的会话上下文更改(他解锁了一项功能)然后他重试访问相同的资源,即一个不同的请求,即没有违反这个建议。
当然,您也可以定义自己的错误代码,但由于它可能不会以任何官方方式保留,因此无法保证某些浏览器制造商不会有意或无意地使用该代码来触发特定的(调试)动作。这不太可能,但不是不允许的。
不过,418 也可以。:)
当然,如果您想特别掩盖功能的潜在可用性,您也可以决定使用 404,因为这是不给爱管闲事的用户任何提示的唯一方法。
现在,对于您的缓存问题:
这些状态代码(403、404、409、418)中的任何一个都不应触发浏览器违反您的意愿缓存页面。问题是许多浏览器只是简单地尝试缓存所有内容以变得更加活泼。在我看来,Opera 是这里最差的。我一直在为这些事情拉头发很多次。应该可以使用正确的标头设置来解决所有问题,但是我遇到过浏览器或服务器或某些中间代理决定忽略它们并无论如何都会破坏我的页面的情况。
到目前为止,我发现的唯一绝对肯定地保证重新加载的可靠方法是添加一个虚拟请求参数,如 /fields?t=29873,其中 29873 是一个数字,对于您在任何可能相关的范围内发出的每个请求都是唯一的时间尺度。当然,在服务器上,您可以简单地忽略此参数。请注意,当您的用户第一次打开您的页面时,仅仅从 1 开始然后计算后续请求是不够的,因为浏览器可能会在页面重新加载时保留缓存。
我在 Java 中进行 Web 开发(服务器和客户端都使用 GWT),并使用此代码生成虚拟“数字”:
private static final char[] base64chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.".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
相反,您可以每 4 毫秒生成大约 1 个值,并且这些值不应在 3200 天内重复。当然,如果用户弄乱了系统时钟,这种保证值不会重复的保证将消失。但由于这些值不是按顺序生成的,因此您仍然不太可能两次点击相同的数字。该代码生成一个 6 字符的文本字符串 (base64) 而不是十进制数字,以使 URL 尽可能短。
希望这可以帮助。:)