Я провел весь день, исследуя и перекодируя, и я не могу заставить это работать. Я создал веб-сайт, который позволяет пользователям входить в систему с использованием своего идентификатора пользователя 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 ... все ловушки, которые упоминали люди. Я не могу понять, почему при использовании электронной почты пользовательские данные исчезают.
Есть предложения?