表单身份验证了解context.user.identity

时间:2012-01-10 21:05:50

标签: c# asp.net forms-authentication

由于此过程的文档非常模糊且令人困惑(或过时),我想验证我是否正确执行此操作并且没有遗漏任何步骤。

我正在尝试创建一个安全的登录系统,在浏览器关闭时到期。

- 在我的web.config中我有以下内容 -

<authentication mode="Forms">
      <forms loginUrl="~/Login.aspx" defaultUrl="Index.aspx" name=".ASPXFORMSAUTH" timeout="100" />
    </authentication>
    <authorization>
      <allow users="?" />
    </authorization>
    <machineKey decryption="AES" validation="SHA1" validationKey.......... />

所以我有一个带有用户名/密码文本框的登录表单和这个按钮:

<asp:Button ID="LoginButton" runat="Server" OnClick="Login_Authenticate" Text="Sign in" />

Inside Login_Authenticate我执行以下操作:

protected void Login_Authenticate(object sender, EventArgs e){
string userName = UserName.Text;
string password = Password.Text;

bool Authenticated = false;

// Here's code that makes sure that Username and Password is CORRECT
if(AuthClass.Authenticate(userName, password)){
 Authenticated = true;
}
// error checking does happen here.

if (Authenticated)
{
  FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(30), rememberUserName, String.Empty, FormsAuthentication.FormsCookiePath);
  string encryptedCookie = FormsAuthentication.Encrypt(ticket);
  HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedCookie);
  cookie.Expires = DateTime.Now.AddMinutes(30);
  Response.Cookies.Add(cookie);
  //FormsAuthentication.RedirectFromLoginPage(userName, false);

  Response.Redirect("MainPage.aspx");
}
}

---在MasterPage.master.cs中,我在Page_Init()---

中进行了以下检查
if (Context.User.Identity.IsAuthenticated)
    {
      int userid = (int)Session["userid"];
      if (userid == null)
      {
        userid = GetUserID(Context.User.Identity.Name);
        if (userid != null)
        {
          Session["userid"] = userid;
        }
      }
    }

修改: --- GLOBAL.ASAX;一些我不太确定的代码是正确的或知道它做了什么

protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        // look if any security information exists for this request
        if (HttpContext.Current.User != null)
        {
            // see if this user is authenticated, any authenticated cookie (ticket) exists for this user
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                // see if the authentication is done using FormsAuthentication
                if (HttpContext.Current.User.Identity is FormsIdentity)
                {
                    // Get the roles stored for this request from the ticket
                    // get the identity of the user
                    FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;
                    //Get the form authentication ticket of the user
                    FormsAuthenticationTicket ticket = identity.Ticket;
                    //Get the roles stored as UserData into ticket
                    string[] roles = { };
                    //Create general prrincipal and assign it to current request

                    HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(identity, roles);
                }
            }
        }
    }

---从那时起,在每个页面上,我使用Session userid收集用户信息和内容,并确保用户具有适当的身份验证和组角色权限。

这一切都正确吗?或者我必须在任何地方解密?

这足以让用户登录安全吗?或者我应该不打扰表单身份验证并找到自己的方式来制作自己的cookie并自己管理它?

4 个答案:

答案 0 :(得分:12)

编写代码的方式登录将在浏览器会话中保持不变。它可能有助于理解正在发生的事情的基础。

对于基于cookie的身份验证方法,实际上有三个操作:

1)登录 - 验证用户的凭据,并在其浏览器上创建并存储cookie。

2)注销 - 只需从浏览器中删除cookie(通过使cookie过期或删除它)

3)Per Request Validation(您的Application_AuthenticateRequest部分) - 检查是否存在cookie,如果存在,请获取用户的Identity和Roles并设置HttpContext.Current.User。

通常,FormsAuthentication模块会隐藏大部分内容。看起来你的代码试图使用FormAuthentication的一些元素(比如FormsAuthenticationTicket和FormsIdentity。只要你得到你想要的东西就没问题。

您的Login_Authenticate方法看起来很好除了您在Cookie上设置过期时。即使您关闭并重新打开浏览器,这也会使cookie保持不变。由于这不是您想要的行为,我不会设置cookie过期。设置此项就像检查“记住我”复选框一样。

每次从应用程序提供页面时,都会运行Application_AuthenticateRequest中的代码。它的主要工作是设置HttpContext.Current.User。通常,如果没有用户登录,则User为null或匿名用户。如果用户已登录,则应代表您的用户。

如果您正在执行这三项操作,那么您可以在代码中的任何位置引用HttpContext.Current.User来决定要显示的信息级别。例如,如果您只想将页面限制为管理员,则可以调用HttpContext.Current.Users.IsInRole(“Administrators”),如果调用返回false,则将它们重定向离开页面。

希望这有帮助。

答案 1 :(得分:6)

我对这个问题有点迟了,但是对于那些试图实现表单身份验证同时保持简单的人(就像我想要的那样),这里是我在msdn上找到的相关最新文档: http://msdn.microsoft.com/en-us/library/xdt4thhy(v=vs.100).aspx

简而言之,不要搞乱设置cookie,检查它们,实例化故障单或校长,......将它留给FormsAuthentication课程。

登录时,如果您的代码具有检查凭据且有效,请致电

FormsAuthentication.RedirectFromLoginPage(yourUserId, false);

它会为您设置身份验证Cookie,与重定向相结合就足够了。 “false”用于不持久授权:它将在浏览器关闭(或授权超时)时丢失。

在已经过身份验证的请求中,没有任何内容可以通过代码进行检查以确保您的身份验证有效。使用Context.User.Identity.Name知道谁已连接(将是上面的字符串yourUserId。)

在显式注销时,请致电

FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();

并在web.config中配置表单身份验证。

<system.web>
  <authentication mode="Forms">
    <forms loginUrl="yourLoginPage" defaultUrl="yourDefaultPageAfterLogin">
    </forms>
  </authentication>
  <authorization>
    <deny users="?" />
  </authorization>
</system.web>

请注意,对于MVC应用程序,应从配置中删除授权部分,并使用AuthorizeAttribute注册为全局过滤器属性进行处理,并在控制器上使用AllowAnonymousAttribute或需要它的操作。 (MVC 4;在此之前,需要创建自己的属性来处理它。)

答案 2 :(得分:2)

授权标签中存在问题,应该是:

<authorization>
  <deny users="?" />
  <allow users="*" />
</authorization>

因为您要拒绝匿名用户。如果您解决了这个问题,您可以安全地从母版页和global.asax中删除所有内容 - 您不必将表单标识重新映射到会话中存储的自定义标识。这是浪费资源,我认为它不会以显着的方式提高解决方案的安全性。您可以依赖表单cookie。

答案 3 :(得分:1)

Remember Me的完整工作流程要求: 1.将自定义数据写入cookie。 2.阅读该自定义数据。

即使你可以通过cookie验证请求,也不意味着HttpSession对象可以恢复该请求。

http://www.codeproject.com/Articles/779844/Remember-Me

enter image description here