3

Я пытаюсь создать свой собственный механизм аутентификации, который основывается на FormsAuthentication. Я в основном использую OAuth, чтобы позволить пользователям проходить аутентификацию на сервере авторизации, и после их аутентификации мне нужно использовать FormsAuthentication для их аутентификации по всему сеансу. Так или иначе, я создал HttpModule и вспомогательный класс, чтобы сделать эту работу. К сожалению, нет.Шифровать и расшифровывать FormsAuthenticationTicket для аутентификации пользователей

Что происходит, так это то, что на PostAuthenticateRequest Я шифрую билет и добавляю к нему куки-файл, а затем перенаправляю пользователя в корень веб-сайта. Как только пользователь перенаправляется, выдается еще один HTTP-запрос, поэтому HttpModule запускается снова, а в событии AuthenticateRequest я проверяю, проверен ли этот пользователь или нет. Чтобы проверить, проверен ли пользователь, я пытаюсь прочитать файл cookie, получить от него имя пользователя, а затем установить свойство Thread.CurrentPrincipal. Но по какой-то причине cookie не может быть найден.

Вот мой код:

public class OAuthModule : IHttpModule 
{ 
    private const String USERNAME = "username"; 

    public void Dispose() 
    { 
    } 

    public void Init(HttpApplication context) 
    { 
     context.AuthenticateRequest += context_AuthenticateRequest; 
     context.PostAuthenticateRequest += context_PostAuthenticateRequest; 
    } 

    void context_PostAuthenticateRequest(object sender, EventArgs e) 
    { 
     var application = sender as HttpApplication; 
     if (application != null) 
     { 
      String username = application.Context.Items[USERNAME].ToString(); 
      String uri = RemoveQueryStringFromUri(application.Context.Request.Url.AbsoluteUri); 
      var cookie = IdentityHelper.GetEncryptedFormsAuthenticationCookie(username, uri); 
      application.Context.Response.Cookies.Add(cookie); 

      application.Context.Response.Redirect(uri); 
     } 
    } 

    void context_AuthenticateRequest(object sender, EventArgs e) 
    { 
     HttpApplication application = sender as HttpApplication; 
     if (sender != null) 
     { 
      if (!application.Context.Request.Url.AbsolutePath.Contains(".")) 
      { 
       if (!IdentityHelper.IsAuthenticated) 
       { 
        HttpContextWrapper wrapper = new HttpContextWrapper(application.Context); 
        String clientId = WebConfigurationManager.AppSettings["ClientId"]; 
        String clientSecret = WebConfigurationManager.AppSettings["ClientSecret"]; 
        String authorizationServerAddress = WebConfigurationManager.AppSettings["AuthorizationServerAddress"]; 
        var client = OAuthClientFactory.CreateWebServerClient(clientId, clientSecret, authorizationServerAddress); 
        if (String.IsNullOrEmpty(application.Context.Request.QueryString["code"])) 
        { 
         InitAuthentication(wrapper, client); 
        } 
        else 
        { 
         OnAuthCallback(wrapper, client); 
        } 
       } 
      } 
     } 
    } 


    private void InitAuthentication(HttpContextWrapper context, WebServerClient client) 
    { 
     var state = new AuthorizationState(); 
     var uri = context.Request.Url.AbsoluteUri; 
     uri = RemoveQueryStringFromUri(uri); 
     state.Callback = new Uri(uri); 
     var address = "https://localhost"; 
     state.Scope.Add(address); 

     OutgoingWebResponse outgoingWebResponse = client.PrepareRequestUserAuthorization(state); 
     outgoingWebResponse.Respond(context); 
    } 

    private void OnAuthCallback(HttpContextWrapper context, WebServerClient client) 
    { 
     try 
     { 
      IAuthorizationState authorizationState = client.ProcessUserAuthorization(context.Request); 
      AccessToken accessToken = AccessTokenSerializer.Deserialize(authorizationState.AccessToken); 
      String username = accessToken.User; 
      context.Items[USERNAME] = username;     
     } 
     catch (ProtocolException e) 
     { 
      EventLog.WriteEntry("OAuth Client", e.InnerException.Message); 
     } 
    } 

    private String RemoveQueryStringFromUri(String uri) 
    { 
     int index = uri.IndexOf('?'); 
     if (index > -1) 
     { 
      uri = uri.Substring(0, index); 
     } 
     return uri; 
    } 
} 


public class IdentityHelper 
{ 
    public static Boolean IsAuthenticated 
    { 
     get 
     { 
      String username = DecryptFormsAuthenticationCookie(); 
      if (!String.IsNullOrEmpty(username)) 
      { 
       SetIdentity(username); 
       return Thread.CurrentPrincipal.Identity.IsAuthenticated; 
      } 
      return false; 
     } 
    } 

    private static String DecryptFormsAuthenticationCookie() 
    { 
     var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 
     if (cookie != null) 
     { 
      FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); 
      return ticket.UserData; 
     } 
     return String.Empty; 
    } 

    internal static HttpCookie GetEncryptedFormsAuthenticationCookie(String username, String domain) 
    { 
     var expires = DateTime.Now.AddMinutes(30); 
     FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, expires, true, username, FormsAuthentication.FormsCookiePath); 
     var cookie = new HttpCookie(FormsAuthentication.FormsCookieName); 
     cookie.Value = FormsAuthentication.Encrypt(ticket); 
     cookie.Domain = domain; 
     cookie.Expires = expires; 
     return cookie; 
    } 

    private static void SetIdentity(String username) 
    { 
     ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim> { new Claim(ClaimTypes.Name, username) }); 
     var principal = new ClaimsPrincipal(claimsIdentity); 
     Thread.CurrentPrincipal = principal; 
    } 
} 

Где я ошибся? Есть идеи?

ответ

0

Хорошо, поэтому я, наконец, решил. Это было так же просто, как:

application.Context.Response.Redirect(uri, false); 

мне нужно сказать модулю, чтобы не убить текущий ответ (отсюда false), так что бы сохранить кук в наступающем запросе.