Как использовать cookie проверки подлинности из службы проверки подлинности WCF в приложении ASP.Net MVC

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

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

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

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

Спасибо заранее.

Ответ 1

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

    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);
            }
        }
    }

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

ИЗМЕНИТЬ

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

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

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

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);
    }
 }