3

に依存する独自の認証メカニズムを作成しようとしていますFormsAuthentication。私は基本的に OAuth を使用して、ユーザーが認可サーバーで認証できるようにしています。認証されたらFormsAuthentication 、セッション全体で認証するために使用する必要があります。とにかく、これを機能さHttpModuleせるために と ヘルパー クラスを作成しました。残念ながら、そうではありません。

何が起こるかというとPostAuthenticateRequest、チケットを暗号化し、応答に Cookie を追加してから、ユーザーを Web サイトのルートにリダイレクトします。ユーザーがリダイレクトされると、別の 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;
    }
}

どこで私は間違えましたか?何か案は?

4

1 に答える 1

0

わかりましたので、最終的に解決しました。次のように簡単でした。

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

現在の応答を強制終了しないようにモジュールに指示する必要がありました (したがってfalse)。これにより、次の要求で Cookie が保持されます。

于 2013-03-15T09:21:07.507 に答える