2010-01-20 2 views
25

Я использую проверку подлинности и отправку запроса Aajx на сервер для аутентификации. На основании результата json клиент решает, куда идти и что делать. Именно по этой причине я не использую FormsAuthentication.RedirectFromLoginPage, чтобы не мешать ответу ajax/json.Как установить Request.IsAuthenticated to true, если не используется FormsAuthentication.RedirectFromLoginPage?

В этом случае Request.IsAuthenticated возвращает false, даже после проверки пользователя с Membership.ValidateUser. Тогда я поставил печенье, используя

FormsAuthentication.SetAuthCookie(username, false); 

Хотя второй параметр, постоянные куки, является ложным, печенье остается в силе во время сеанса браузера.

Любая идея, как заставить Request.IsAuthenticated работать без использования FormsAuthentication.RedirectFromLoginPage?

+0

Возможно, вы не устанавливать куки правильно используя запрос AJAX ... – Jason

+0

Вы пытались следовать инструкциям MSDN по адресу: //msdn.microsoft.com/en-us/library/bb398896.aspx? –

+0

Это особенно проблематично, если вы пытаетесь создать и вернуть токен анти-подделки в свой запрос на аутентификацию ajax (т. Е. SPA). Asp.Net будет генерировать токен для пользователя «», поскольку он предполагает, что никто в настоящее время не аутентифицирован. – SeeNoWeevil

ответ

22

Вам необходимо обновить текущий ключ безопасности для запроса. Когда вы вызываете Response. Redirect(...), выполняется новый запрос, а принципал безопасности повторно инициализируется, а Request.IsAuthenticated возвращает true в вашем случае. FormsAuthentication.RedirectFromLoginPage Внутренние звонки Response. Redirect(...). Вы можете вручную обновить принципал безопасности для текущего запроса, как это:

public void RenewCurrentUser() 
{ 
    System.Web.HttpCookie authCookie = 
     System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 
    if (authCookie != null) 
    { 
     FormsAuthenticationTicket authTicket = null; 
     authTicket = FormsAuthentication.Decrypt(authCookie.Value); 

     if (authTicket != null && !authTicket.Expired) 
     { 
      FormsAuthenticationTicket newAuthTicket = authTicket; 

      if (FormsAuthentication.SlidingExpiration) 
      { 
       newAuthTicket = FormsAuthentication.RenewTicketIfOld(authTicket); 
      } 
      string userData = newAuthTicket.UserData; 
      string[] roles = userData.Split(','); 

      System.Web.HttpContext.Current.User = 
       new System.Security.Principal.GenericPrincipal(new FormsIdentity(newAuthTicket), roles); 
     } 
    } 
} 
+0

Обновление вручную не требуется (особенно для GenericPrincipal и FormsIdentity), а учетные данные не должны меняться частично через запрос, поэтому cookie добавляется в ответ, а затем выполняется полностью новый жизненный цикл ответа/запроса. По следующему запросу будет выбран файл cookie, созданный FormsAuthentication.SetAuthCookie(). –

+4

Конечно, этот метод можно считать взломом, потому что он не соответствует потоку аутентификации обычной формы. Но это может быть полезно, если вы хотите проверить, аутентифицирован ли пользователь в том же запросе, в котором используется аутентификация. –

+1

Иногда, хотя взлом - это то, что вам нужно - я пытался что-то делать «правильно» и заставлял перенаправлять, и попадал в правильное состояние с перенаправленными другими системами :( –

20

FormsAuthentication.SetAuthCookie

Метод Создает аутентификацию билет на поставляемом имя пользователя и добавляет его в коллекцию печенья ответ или URL, если вы используете , используя аутентификацию cookieless.

Ref: msdn

Посмотрите на Forms Authentication Control Flow. Куки-файл проверки подлинности настроен на коллекцию файлов ответов и должен быть доступен на уровне протокола HTTP (например, используйте FireCookie или Fiddler2 для проверки этого).

Членство только подтверждает имя пользователя/пароль. Ни членство, ни SetAuthCookie() не изменят текущий запрос. Они ожидают отправить cookie обратно вызывающему абоненту, а следующий запрос - это когда свойства, подобные IsAuthenticated, вернутся.

Обратите внимание, что вы можете изменить и расширить эти автоматических процессов с помощью пользовательских IIdentity и IPrincipal, и зацепить события аутентификации, если вам нужно.

также посмотреть на Using Forms Authentication with ASP.NET AJAX

+0

Это отличный ответ. – Greg

+1

+1 для проверки подлинности контроля форм Form. – CGK

+0

Я использовал Fiddler для просмотра файлов cookie в запросе и ответе –

2

Перенаправление после POST наилучшей практикой, и следует считать правильным решением.

В некоторых случаях вы все равно можете выяснить, аутентифицирован ли пользователь в пределах области запроса аутентификации (например, если вы выполняете дополнительную логику после выполнения проверки подлинности, которая используется совместно с другими запросами).

В этом случае вы можете сбросить значение запроса.IsAuthenticated со следующим кодом:

// set the forms auth cookie 
FormsAuthentication.SetAuthCookie(username, createPersistentCookie); 

// reset request.isauthenticated 
var authCookie = System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 
if (authCookie != null) 
{ 
    FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
    if (authTicket != null && !authTicket.Expired) 
    { 
     var roles = authTicket.UserData.Split(','); 
     System.Web.HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles); 
    } 
} 

См пост здесь: http://abadjimarinov.net/blog/2010/01/24/RenewUserInTheSameRequestInAspdotNET.xhtml

Смежные вопросы