знаю, что есть много вопросов, связанных с проверкой подлинности с помощью форм и сохранением файлов cookie, но, потратив большую часть дня на изучение, я все еще испытываю трудности.
Моя проблема
Я работаю над веб-приложением (VS2010, но webapp - версия 3.5), которое ограничивает доступ к определенным частям приложения для аутентифицированных пользователей (тогда как другие части открыты).Моя проблема в том, что мои куки-файлы аутентификации не сохраняются после закрытия браузера.
Мой подход
Я написал простую страницу login.aspx, которая настроена в web.config следующим образом:
<authentication mode="Forms">
... и поведение отдельных страниц объявляется так:
<location path="ClientManageAccount.aspx">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
..., который прекрасно работает во всех отношениях, КРОМЕ этого феномена cookie ...
Я создаю куки-файл аутентификации вручную, как только я аутентифицировал логин и пароль моего пользователя по базе данных (которая отлично работает) на странице login.aspx.Если пользователь установит флажок «держать меня в системе», файл cookie будет создан с использованием этого метода:
private void GenerateAuthenticationCookie(int expiryInMinutes, Guid userGuid)
{
DateTime cookieExpiration = DateTime.Now.AddMinutes(expiryInMinutes); // change to months for production
var authenticationTicket =
new FormsAuthenticationTicket(
2,
userGuid.ToString(),
DateTime.Now,
cookieExpiration,
true,
string.Empty,
FormsAuthentication.FormsCookiePath);
// ticket must be encrypted
string encryptedTicket = FormsAuthentication.Encrypt(authenticationTicket);
// create cookie to contain encrypted auth ticket
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
authCookie.Expires = authenticationTicket.Expiration;
authCookie.Path = FormsAuthentication.FormsCookiePath;
// clear out existing cookie for good measure (probably overkill) then add
HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
HttpContext.Current.Response.Cookies.Add(authCookie);
}
Цель состоит в том, чтобы сохранить Guid пользователя в файле cookie авторизации, который я затем буду использоватьвосстановить объект пользователя в сеансе (это также на странице login.aspx, и я думаю, что я хотел бы извлечь guid пользователя из созданного мной файла cookie auth и использовать его для заполнения соответствующей записи пользователяв сеанс и перенаправьте на запрошенную страницу):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TryAutoLogin();
}
}
private void TryAutoLogin()
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
if (ticket != null)
{
if (ticket.Name.Length > 0)
{
try
{
Guid userGuid = new Guid(ticket.Name);
KUser user = UserFunctions.GetUserFromUserGuid(userGuid);
if (user != null) Session["User"] = user;
FormsAuthentication.RedirectFromLoginPage(userGuid.ToString(), true);
}
catch (Exception anyException)
{
// don't do anything for now - do something smart later :-) }
}
}
}
}
Наконец, вот код кнопки входа в систему на моей странице login.aspx:
protected void Submit_OnClick(object sender, EventArgs e)
{
long userId = 0;
UserAuthenticationStatus status;
status = (UserAuthenticationStatus)UserFunctions.UserAuthenticates(EmailAddress.Text, Password.Text, ref userId);
switch (status)
{
case UserAuthenticationStatus.Authenticated:
//email address and password match, account ok, so log this user in
KUser user = UserFunctions.GetUser(userId);
Session["User"] = user;
if (ChkRememberMe.Checked)
{
GenerateAuthenticationCookie(15, user.UserGuid); // 15 minutes
FormsAuthentication.RedirectFromLoginPage(user.UserGuid.ToString(), true);
}
else
{
FormsAuthentication.RedirectFromLoginPage(user.UserGuid.ToString(), false);
}
break;
case UserAuthenticationStatus.AuthButLocked:
// email/pwd match but account is locked so do something
ShowLockedAccountMessage();
break;
case UserAuthenticationStatus.EmailFoundIncorrectPassword:
case UserAuthenticationStatus.EmailNotFound:
case UserAuthenticationStatus.Unknown:
// either the email wasn't found, or the password was incorrect or there was some other problem
// present message stating this and offer chance to register
ShowFailedLoginMessage();
break;
default:
ShowUnavailableMessage();
break;
}
}
Как видите,в этом нет ничего особенно сложного, но несмотря на то, что authCookie, созданный в GenerateAuthenticationCookie (..), создается правильно (насколько я могу судить), он не сохраняется.
Одна вещь, которую я заметилявляется то, что, если я помещаю некоторый код в метод Application_AuthenticateRequest в global.asax.cs, например:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie != null)
{
int x = 4; // just a dummy line so that I can set a breakpoint
}
}
... эта точка остановаколичество попаданий после нового сеанса браузера, хотя оно перестает срабатывать, как только я ухожу со страницы запуска (в данном случае фиктивная страница start.aspx, используемая исключительно для разработки и тестирования).
Итак, извинения за длинный вопрос, но я действительно страдаю здесь.
Вещи, которые я проверял / пробовал
Обеспечение выполнения кода - ДАНастройки браузера - т.е. нет удаления файлов cookie при выходе - ПОДТВЕРЖДЕНО, НЕТ УДАЛЕНИЯ Попытка использовать разные тайм-ауты - например, они равны или отличаются от таймаута web.config, кажется, не имеет значения ... ... и, конечно, по крайней мере двадцать или тридцать разныхпредыдущие вопросы, но безрезультатно.
System / Dev Environment
Windows 7 64-bit, VS2010 (но proj is 3.5), SQL Server 2008 Express.
На моем dev-сервере эта проблема остается, поэтому я не уверен, что она обязательно является экологической - эта машина является блоком WS2008R2, на котором выполняется SQL 2008R2 - и та же проблема остается.
Кто-нибудь, кто-нибудь, когда-нибудьу вас есть идеи, что я могу попробовать здесь?У меня есть предчувствие, что я мог бы заставить это работать, перехватывая начальный удар Application_AuthenticateRequest в global.asax.cs и вставляя что-то в состояние сеанса, чтобы пометить его как «authenticated» (чтобы избежать дорогостоящей попытки аутентификации каждый раз, когда вызывается этот метод, что оказываетсябыть несколько раз на странице.
Заранее спасибо,
Джон