How to use authentication cookie from WCF Authentication Service in an ASP.Net MVC application

后端 未结 2 1364
慢半拍i
慢半拍i 2021-01-30 11:57

Okay, I\'ve had little luck finding any documentation or tutorials for my specific scenario.

I have an ASP.Net MVC web application that will be using WCF services for ev

相关标签:
2条回答
  • 2021-01-30 12:39

    I have recently been trying to implement the same functionality you have described. I have managed to get it working with the following code:

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

    It does exactly what you have described the comment to your question.

    EDIT

    I am posting here the Server-Side portion of this code for reference.

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-30 12:47

    This works for me... First setup the authentication behavior of the host (here shown through code, but can also be done in config):

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

    And then the helper classes

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

    And for when AspNetCompatibility is set, then FormCookieServiceAuthorizationManager is slightly simpler:

     internal class FormCookieServiceAuthorizationManager : ServiceAuthorizationManager
     {
        public override bool CheckAccess(OperationContext operationContext)
        {
           Thread.CurrentPrincipal = HttpContext.Current.User;
           return base.CheckAccess(operationContext);
        }
     }
    
    0 讨论(0)
提交回复
热议问题