3

我试图创建我自己的身份验证机制,它依赖于FormsAuthentication。我基本上使用OAuth来允许用户在授权服务器中进行身份验证,一旦他们通过身份验证,我需要使用FormsAuthentication在会话中对其进行身份验证。所以无论如何,我创建了一个HttpModule和一个辅助类来完成这个工作。不幸的是,事实并非如此。加密和解密FormsAuthenticationTicket以验证用户

发生什么事是在PostAuthenticateRequest我加密票证并添加一个cookie到响应,然后将用户重定向到网站的根目录。一旦用户被重定向,另一个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),因此它会保存在今后请求的cookie。