asp.net Установка FormsAuthentication Cookie вручную приводит к потере пользовательских данных на главной странице сайта - PullRequest
0 голосов
/ 04 января 2019

Я провел весь день, исследуя и перекодируя, и я не могу заставить это работать. Я создал веб-сайт, который позволяет пользователям входить в систему с использованием своего идентификатора пользователя Active Directory (sAMAccountName) или адреса электронной почты (userPrincipalName). Он читает AD, проверяет пользователя и сохраняет userData в куки. По пути я проверил несколько пунктов, и данные остаются в файле cookie, пока не попадут на главную страницу моего сайта.

Файл web.config выглядит следующим образом:

<authentication mode="Forms">
  <forms loginUrl="~/login.aspx" slidingExpiration="true" defaultUrl="default.aspx" name=".ADAuthCookie" timeout="864000" />
</authentication>
<membership defaultProvider="MyADMembershipProvider_PrincipalName">
  <providers>
    <clear />
    <add name="MyADMembershipProvider_AccountName" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
    <add name="MyADMembershipProvider_PrincipalName" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" attributeMapUsername="userPrincipalName" />
  </providers>
</membership>

Пользователь вводит информацию и нажимает кнопку «Войти», эта функция срабатывает:

protected void Login_Click(object sender, CommandEventArgs e)
{
    authCookie ac = new authCookie();
    myUtils mu = new myUtils();

    string userID = (LoginUser.FindControl("UserName") as TextBox).Text;
    string userPW = (LoginUser.FindControl("Password") as TextBox).Text;

    MembershipProvider dp;

    //Search for @ in the value typed into the User ID box to see if they are logging
    //in using their e-mail address or User ID, and assign the appropriate AD lookup
    int amper = userID.IndexOf("@");

    switch (amper)
    {
        case -1:    //login id used
            dp = Membership.Providers["MyADMembershipProvider_AccountName"];
            break;
        default:    //email address used
            dp = Membership.Providers["MyADMembershipProvider_PrincipalName"];
            break;
    }

    //Verify if the user is in Active Directory or that Jimmy is debugging...
    if ((dp.ValidateUser(userID, userPW)) || (HttpContext.Current.Request.IsLocal))
        ac.cookiePrep(LoginUser);
    else if (mu.isTestAccount(userID, userPW))  //someone is logging in with a testAccount
        ac.cookiePrep(LoginUser);
    else
    {
        ((Label)LoginUser.FindControl("accessDenied")).Visible = true;
        Response.Write("Invalid UserID and Password");
    }
}

Метод ac.cookiePrep, который вызывается, выглядит следующим образом:

public void cookiePrep(Login LoginUser)
{
    string userData = "unknown|unknown";

    // Concat the values into a single string to pass into the cookie
    userData = getUserData(LoginUser.UserName);

    // Create the cookie that contains the forms authentication ticket
    HttpCookie authCookie = FormsAuthentication.GetAuthCookie(LoginUser.UserName, LoginUser.RememberMeSet);

    // Get the FormsAuthenticationTicket out of the encrypted cookie
    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
    FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(2,
                                                                        ticket.Name,
                                                                        ticket.IssueDate,
                                                                        ticket.Expiration,
                                                                        LoginUser.RememberMeSet,
                                                                        userData,
                                                                        ticket.CookiePath);

    // Manually add the authCookie to the Cookies collection
    authCookie.Value = FormsAuthentication.Encrypt(newTicket);
    HttpContext.Current.Response.Cookies.Add(authCookie);

    //string redirUrl = FormsAuthentication.GetRedirectUrl(LoginUser.UserName, LoginUser.RememberMeSet);

    //if (redirUrl == null)
        //redirUrl = "../default.aspx";

    //HttpContext.Current.Response.Redirect(redirUrl, false);
}

Я позвонил в cookie в самом конце функции Login_click, чтобы убедиться, что userData все еще там ... это было. На этом этапе происходит любая используемая магия перенаправления, и пользователь перенаправляется на главную страницу по умолчанию / главную страницу, где вызывается главная страница сайта. В этот момент я вставил вызов файла cookie в начало первой вызванной функции, а userData отсутствует.

protected void Page_Init(object sender, EventArgs e)
{
    HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
    }

    // The code below helps to protect against XSRF attacks
    var requestCookie = Request.Cookies[AntiXsrfTokenKey];
    Guid requestCookieGuidValue;
    if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
    {
        // Use the Anti-XSRF token from the cookie
        _antiXsrfTokenValue = requestCookie.Value;
        Page.ViewStateUserKey = _antiXsrfTokenValue;
    }
    else
    {
        // Generate a new Anti-XSRF token and save to the cookie
        _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
        Page.ViewStateUserKey = _antiXsrfTokenValue;

        var responseCookie = new HttpCookie(AntiXsrfTokenKey)
        {
            HttpOnly = true,
            Value = _antiXsrfTokenValue
        };
        if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
        {
            responseCookie.Secure = true;
        }
        Response.Cookies.Set(responseCookie);
    }

    Page.PreLoad += master_Page_PreLoad;
}

Так что вот где это становится более странным ... или, может быть, в этом проблема, и я просто не понимаю этого. Если пользователь входит в систему со своим идентификатором пользователя, userData НЕ теряется. Однако если они выйдут из системы и попытаются снова войти в систему со своим адресом электронной почты, именно тогда данные пользователя теряются на главной странице.

Я читал и не использую метод GetRedirectURL (вы можете видеть, что он закомментирован), и я использую Response.Add, захватывая cookie с помощью Request ... все ловушки, которые упоминали люди. Я не могу понять, почему при использовании электронной почты пользовательские данные исчезают.

Есть предложения?

...