Как использовать куки аутентификации из службы аутентификации WCF в приложении ASP.Net MVC - PullRequest
14 голосов
/ 06 апреля 2010

Хорошо, мне не повезло найти документацию или руководства для моего конкретного сценария.

У меня есть веб-приложение ASP.Net MVC, которое будет использовать службы WCF для всего, включая проверку подлинности и роли (через поставщиков членства в бэкенде WCF).

У меня не было проблем при настройке служб аутентификации , но он не устанавливает cookie в веб-приложении. Документы для метода входа службы указывают, что подключение EventCookie Event возможно, но оно не оказывает никакого влияния на клиента (я также пробовал на стороне службы, опять же, никакого влияния). Итак, я понял, как захватить cookie . Я пытался вручную установить файл cookie для аутентификации на клиенте, но пока он не работает; сбой расшифровки из-за заполнения, а установка значения cookie из значения, указанного сервером, не читается клиентом.

Кто-нибудь знает, как вы должны использовать cookie, сгенерированный службой аутентификации WCF? Должен ли я просто предполагать, что сеанс полностью управляется на сервере WCF, и просто проверять IsLoggedIn () в службе при каждой загрузке страницы?

Заранее спасибо.

Ответы [ 2 ]

11 голосов
/ 14 апреля 2010

Недавно я пытался реализовать ту же функциональность, которую вы описали. Мне удалось заставить его работать со следующим кодом:

    private readonly AuthenticationServiceClient service = new AuthenticationServiceClient();

    public void SignIn(string userName, string password, bool createPersistentCookie)
    {
        using (new OperationContextScope(service.InnerChannel))
        {
            // login
            service.Login(userName, password, String.Empty, createPersistentCookie);

            // Get the response header
            var responseMessageProperty = (HttpResponseMessageProperty)
                OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];

            string encryptedCookie = responseMessageProperty.Headers.Get("Set-Cookie");

            // parse header to cookie object
            var cookieJar = new CookieContainer();
            cookieJar.SetCookies(new Uri("http://localhost:1062/"), encryptedCookie);
            Cookie cookie = cookieJar.GetCookies(new Uri("http://localhost:1062/"))[0];

            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
            if (null != ticket)
            {
                //string[] roles = RoleManager.GetRolesFromString(ticket.UserData); 
                HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(ticket), null);
                FormsAuthentication.SetAuthCookie(HttpContext.Current.User.Identity.Name, createPersistentCookie);
            }
        }
    }

Это именно то, что вы описали в комментарии к вашему вопросу.

EDIT

Я публикую здесь серверную часть этого кода для справки.

public class HttpResponseMessageInspector : BehaviorExtensionElement, IDispatchMessageInspector, IServiceBehavior
{
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {

        HttpRequestMessageProperty httpRequest = request.Properties[HttpRequestMessageProperty.Name]
        as HttpRequestMessageProperty;

        if (httpRequest != null)
        {
            string cookie = httpRequest.Headers[HttpRequestHeader.Cookie];

            if (!string.IsNullOrEmpty(cookie))
            {
                FormsAuthentication.Decrypt(cookie);
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(cookie);
                string[] roles = PrincipalHelper.GetUserRoles(authTicket);
                var principal = new BreakpointPrincipal(new BreakpointIdentity(authTicket), roles);

                HttpContext.Current.User = principal;                  
            }
            // can deny request here
        }

        return null;
    }
}
2 голосов
/ 09 мая 2012

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

ServiceAuthorizationBehavior author = Description.Behaviors.Find<ServiceAuthorizationBehavior>();
author.ServiceAuthorizationManager = new FormCookieServiceAuthorizationManager();
author.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
author.ExternalAuthorizationPolicies = new List<IAuthorizationPolicy> { new CustomAuthorizationPolicy() }.AsReadOnly();

А потом вспомогательные классы

  internal class FormCookieServiceAuthorizationManager : ServiceAuthorizationManager
  {
     public override bool CheckAccess(OperationContext operationContext)
     {
        ParseFormsCookie(operationContext.RequestContext.RequestMessage);
        return base.CheckAccess(operationContext);
     }
     private static void ParseFormsCookie(Message message)
     {
        HttpRequestMessageProperty httpRequest = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
        if (httpRequest == null) return;

        string cookie = httpRequest.Headers[HttpRequestHeader.Cookie];
        if (string.IsNullOrEmpty(cookie)) return;

        string regexp = Regex.Escape(FormsAuthentication.FormsCookieName) + "=(?<val>[^;]+)";
        var myMatch = Regex.Match(cookie, regexp);
        if (!myMatch.Success) return;

        string cookieVal = myMatch.Groups["val"].ToString();
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(cookieVal);
        Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), new string[0]);
     }
  }
  internal class CustomAuthorizationPolicy : IAuthorizationPolicy
  {
     static readonly string _id = Guid.NewGuid().ToString();
     public string Id
     {
        get { return _id; }
     }

     public bool Evaluate(EvaluationContext evaluationContext, ref object state)
     {
        evaluationContext.Properties["Principal"] = Thread.CurrentPrincipal;
        evaluationContext.Properties["Identities"] = new List<IIdentity> { Thread.CurrentPrincipal.Identity };
        return true;
     }

     public ClaimSet Issuer
     {
        get { return ClaimSet.System; }
     }
  }

А если установлена ​​AspNetCompatibility, то FormCookieServiceAuthorizationManager немного проще:

 internal class FormCookieServiceAuthorizationManager : ServiceAuthorizationManager
 {
    public override bool CheckAccess(OperationContext operationContext)
    {
       Thread.CurrentPrincipal = HttpContext.Current.User;
       return base.CheckAccess(operationContext);
    }
 }
...