加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

ASP.NET Forms身份验证超时

发布时间:2020-12-15 23:30:14 所属栏目:asp.Net 来源:网络整理
导读:这可能是一个非常简单的问题,但是经过几个小时试图了解ASP.NET 4.0的工作原理,我还是不知道. 我正在使用表单验证.我有一个具有登录控件的登录页面. 这是用户登录时需要的: A-用户应该保持记录,直到超时设置不做任何事情.如果他们重新加载页面,超时必须重新
这可能是一个非常简单的问题,但是经过几个小时试图了解ASP.NET 4.0的工作原理,我还是不知道.

我正在使用表单验证.我有一个具有登录控件的登录页面.

这是用户登录时需要的:

A-用户应该保持记录,直到超时设置不做任何事情.如果他们重新加载页面,超时必须重新启动倒计时.

B-如果他们点击“记住我”检查,他们应该保持连接,直到他们注销,无论他们关闭浏览器还是重新启动计算机.

我遇到的问题是登录时,我的电脑上没有看到任何cookie:

> Cookie在哪里?是内存cookie吗?
>会话过期会怎么样?我想保持他们记录,除非超时完成.
>如果应用程序池被回收,会发生什么?

另外我有另一个问题:当他们点击“记住我”检查(案例B),我希望他们记录,直到他们点击注销按钮.这一次我看到一个cookie,但是看起来他们只是为了超时而保持联系…所以Rememeber我有什么区别?

我想完全分离身份验证和会话.我想要通过cookie控制的身份验证,如果接近不是很差.

谢谢你的帮助.

解决方法

处理非永久性,滑动过期票

表单身份验证使用内存中的Cookie作为故障单,除非您使其持久化(例如,FormsAuthentication.SetAuthCookie(username,true)将使其持久).默认情况下,票证使用滑动到期.每次处理请求时,票据将以新的到期日期向下发送.该日期到期后,Cookie和机票都是无效的,用户将被重定向到登录页面.

表单身份验证没有内置的方法来重定向已经呈现的页面,这些页面比超时时间长.您将需要自己添加.在最简单的层面上,您将需要使用JavaScript启动带有文档加载的计时器.

<script type="text/javascript">
  var redirectTimeout = <%FormsAuthentication.Timeout.TotalMilliseconds%>
  var redirectTimeoutHandle = setTimeout(function() { window.location.href = '<%FormsAuthentication.LoginUrl%>'; },redirectTimeout);
</script>

使用上述方法,如果您的页面没有刷新或更改,或者redirectTimeoutHandle没有被其他方式取消(使用clearTimeout(redirectTimeoutHandle);),它将被重定向到登录页面. FormsAuth机票应该已经过期,所以你不应该做任何事情.

这里的诀窍是您的网站是否执行AJAX工作,或者您将其他客户端事件视为活动用户活动(移动或单击鼠标等).您将必须手动跟踪这些事件,当它们发生时,重置redirectTimeoutHandle.例如,我有一个使用AJAX的站点,所以页面不会经常刷新.由于我使用jQuery,所以每次发出一个AJAX请求时,我都可以重新设置这个超时时间,实际上,如果它们位于单个页面上,而不进行任何更新,那么这个页面将被重定向.

这是一个完整的初始化脚本.

$(function() {
   var _redirectTimeout = 30*1000; // thirty minute timeout
   var _redirectUrl = '/Accounts/Login'; // login URL

   var _redirectHandle = null;

   function resetRedirect() {
       if (_redirectHandle) clearTimeout(_redirectHandle);
       _redirectHandle = setTimeout(function() { window.location.href = _redirectUrl; },_redirectTimeout);
   }

   $.ajaxSetup({complete: function() { resetRedirect(); } }); // reset idle redirect when an AJAX request completes

   resetRedirect(); // start idle redirect timer initially.
});

通过简单地发送AJAX请求,客户端超时和票据(以cookie的形式)将被更新,您的用户应该是正常的.

但是,如果用户活动不会导致更新FormsAuth故障单,则用户在下一次请求新页面(通过导航或通过AJAX)时将显示为注销.在这种情况下,当用户活动发生在AJAX调用(例如自定义处理程序,MVC操作等)时,您需要“ping”您的Web应用程序,以使您的FormsAuth票证保持最新.请注意,在ping服务器以保持最新时,您需要小心,因为您不希望洪泛服务器的请求,例如,移动光标或点击事物.除了初始页面加载和AJAX请求之外,还有一个除了初始化脚本之外的添加,将resetRedirect添加到文档上的鼠标点击.

$(function() {
   $(document).on('click',function() {
      $.ajax({url: '/ping.ashx',cache: false,type: 'GET' }); // because of the $.ajaxSetup above,this call should result in the FormsAuth ticket being updated,as well as the client redirect handle.
   });
});

处理“永久”门票

您需要将票证作为持久性Cookie发送到客户端,并且具有任意长的超时时间.您应该能够直接离开客户端代码和web.config,而是在登录逻辑中单独处理用户对常规故障单的偏好.在这里,您需要修改机票.以下是登录页面中的逻辑来做这样的事情:

// assumes we have already successfully authenticated

if (rememberMe)
{
    var ticket = new FormsAuthenticationTicket(2,userName,DateTime.Now,DateTime.Now.AddYears(50),true,string.Empty,FormsAuthentication.FormsCookiePath);
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,FormsAuthentication.Encrypt(ticket))
                     {
                         Domain = FormsAuthentication.CookieDomain,Expires = DateTime.Now.AddYears(50),HttpOnly = true,Secure = FormsAuthentication.RequireSSL,Path = FormsAuthentication.FormsCookiePath
                     };
    Response.Cookies.Add(cookie);
    Response.Redirect(FormsAuthentication.GetRedirectUrl(userName,true));
}
else
{
    FormsAuthentication.RedirectFromLoginPage(userName,false);
}

奖金:在角色中存储角色

你问你是否可以在门票/ cookie中存储角色,所以你不必再看看.是的,这是可能的,但有一些考虑.

>您应该限制您在票中放入的数据量,因为Cookie只能这么大
>你应该考虑是否应该在客户端缓存角色.

详细说明#2:

您不应隐含地信任您从用户那里收到的声明.例如,如果用户登录并且是管理员,并检查“记住我”,从而接收持久的长期票证,他们将永远是管理员(或直到该cookie过期或被删除).如果有人从您的数据库中删除该角色,则应用程序仍然认为他们是管理员,如果他们有旧票.因此,您可能会更好地每次获取用户的角色,但是在应用程序实例中缓存角色一段时间,以最大限度地减少数据库的工作.

从技术上讲,这也是机票本身的一个问题.再次,你不应该相信这只是因为他们有一个有效的票证,该帐户仍然有效.您可以使用与角色类似的逻辑:检查由票证引用的用户是否仍然存在,并且通过查询实际的数据库是有效的(它不被锁定,禁用或删除),并且仅缓存数据库结果一段时间时间来提高性能.这是我在我的应用程序中所做的那样,其中机票被视为身份声明(同样,用户名/密码是另一种类型的声明).以下是global.asax.cs(或HTTP模块)中的简化逻辑:

protected void Application_AuthenticateRequest(Object sender,EventArgs e)
{
  var application = (HttpApplication)sender;
  var context = application.Context;  

  EnsureContextUser(context);
}

private void EnsureContextUser(HttpContext context)
{
   var unauthorizedUser = new GenericPrincipal(new GenericIdentity(string.Empty,string.Empty),new string[0]);

   var user = context.User;

   if (user != null && user.Identity.IsAuthenticated && user.Identity is FormsIdentity)
   {
      var ticket = ((FormsIdentity)user.Identity).Ticket;

      context.User = IsUserStillActive(context,ticket.Name) ? new GenericPrincipal(user.Identity,GetRolesForUser(context,ticket.Name)) : unauthorizedUser;

      return; 
   }

   context.User = unauthorizedUser;
}

private bool IsUserStillActive(HttpContext context,string username)
{
   var cacheKey = "IsActiveFor" + username;
   var isActive = context.Cache[cacheKey] as bool?

   if (!isActive.HasValue)
   {
      // TODO: look up account status from database
      // isActive = ???
      context.Cache[cacheKey] = isActive;
   }

   return isActive.GetValueOrDefault();
}

private string[] GetRolesForUser(HttpContext context,string username)
{
   var cacheKey = "RolesFor" + username;
   var roles = context.Cache[cacheKey] as string[];

   if (roles == null)
   {
      // TODO: lookup roles from database
      // roles = ???
      context.Cache[cacheKey] = roles;
   }

   return roles;
}

当然,你可能会决定你不关心任何一个,只是想相信票,并把角色存放在票上.首先,我们从上面更新您的登录逻辑:

// assumes we have already successfully authenticated

if (rememberMe)
{
    var ticket = new FormsAuthenticationTicket(2,GetUserRolesString(),true));
}
else
{
    var ticket = new FormsAuthenticationTicket(2,DateTime.Now.AddMinutes(FormsAuthentication.Timeout),false,FormsAuthentication.FormsCookieName);
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,FormsAuthentication.Encrypt(ticket))
       {
          Domain = FormsAuthentication.CookieDomain,Path = FormsAuthentication.FormsCookiePath
       };
    Response.Cookies.Add(cookie);
    Response.Redirect(FormsAuthentication.GetRedirectUrl(userName,false));
}

添加方法:

private string GetUserRolesString(string userName)
   {
        // TODO: get roles from db and concatenate into string
   }

更新您的global.asax.cs以获取角色,并更新HttpContext.User:

protected void Application_AuthenticateRequest(Object sender,EventArgs e)
{
  var application = (HttpApplication)sender;
  var context = application.Context;  

  if (context.User != null && context.User.Identity.IsAuthenticated && context.User.Identity is FormsIdentity)
  {
      var roles = ((FormsIdentity)context.User.Identity).Ticket.Data.Split(",");

      context.User = new GenericPrincipal(context.User.Identity,roles);
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读