您可以实现自定义授权,以在有限的时间内允许匿名浏览,如下所示:
public class AuthorizeWithAnonymousTimeoutAttribute : AuthorizeAttribute
{
public int? AnonymousMinutesTimeout { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
// Let default handling occurs
base.OnAuthorization(filterContext);
// If result is set, authorization has already been denied,
// nothing more to do.
if (filterContext.Result as HttpUnauthorizedResult != null)
return;
var isAnonAllowed = filterContext.ActionDescriptor.IsDefined(
typeof(AllowAnonymousAttribute), true) ||
filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(
typeof(AllowAnonymousAttribute), true);
if (isAnonAllowed && AnonymousMinutesTimeout.HasValue &&
// Not authorized
!AuthorizeCore(filterContext.HttpContext))
{
const string visitStartCookieName = "visitStartCookie";
const string visitStartDateFormat = "yyyyMMddhhmmss";
var visitStartCookie = filterContext.HttpContext.Request
.Cookies[visitStartCookieName];
var now = DateTime.UtcNow;
DateTime visitStartDate;
var visitStartCookieValid = visitStartCookie != null &&
DateTime.TryParseExact(visitStartCookie.Value,
visitStartDateFormat, null, DateTimeStyles.AssumeUniversal,
out visitStartDate);
if (!visitStartCookieValid)
{
visitStartDate = now;
filterContext.HttpContext.Response.Cookies.Add(
// Session cookie. (Need to set an expiry date if
// a "permanent" cookie is wished instead.)
new HttpCookie
{
Name = "visitStartCookie",
Value = now.ToString(visitStartDateFormat)
});
}
if (visitStartDate.AddMinutes(AnonymousMinutesTimeout.Value) < now)
{
// Anonymous visit timed out
HandleUnauthorizedRequest(filterContext);
return;
}
}
}
}
然后,如果它适合您,请将其用作全局过滤器,如下所示:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(
new AuthorizeWithAnonymousTimeoutAttribute
{
// By example, 10 minutes
AnonymousMinutesTimeout = 10
});
// Your other filters
...
}
别忘了用AllowAnonymousAttribute装饰你的控制器或动作:
[AllowAnonymous]
public class YourController
{
}
或者
public class YourController
{
[AllowAnonymous]
public ActionResult YourAction()
{
}
}
如果全局定义不适合您,您也可以将自定义授权属性直接放在控制器或操作上:
// By example, 10 minutes anonymous browsing allowed.
[AuthorizeWithAnonymousTimeout(AnonymousMinutesTimeout = 10)]
public class YourController
{
}
请注意,此实现不保证匿名超时。只要他愿意,黑客就可以克服它并匿名浏览。浏览器工具允许删除 cookie,因此很容易从新的超时开始。
我的示例还只是设置了一个会话 cookie,它会通过关闭/重新打开浏览器而消失。当然,使用其他浏览器或设备可以再使用 10 分钟。
确保匿名超时非常困难,因为您的用户是匿名的。您可以尝试从他们的技术特征中识别您的匿名用户,然后在服务器端跟踪他们的超时时间。
但是您可能会遇到很多问题:企业用户使用相同的 IP 地址浏览,或者因为没有单一的 Internet 连接而在不同的 IP 之间切换,...