简体   繁体   English

具有SSO的自托管WCF服务器

[英]Self-hosted WCF Server with SSO

We've got a self-hosted WCF service that is hosting content over HTTP and would like to be able to support single sign-on with Windows / AD. 我们有一个自托管的WCF服务,该服务通过HTTP托管内容,并希望能够支持Windows / AD的单点登录。 Ideally this would support IE, Firefox and Chrome. 理想情况下,它将支持IE,Firefox和Chrome。

I've built the following sample service that returns some plain text over HTTP. 我构建了以下示例服务,该服务通过HTTP返回一些纯文本。 Note: in the production version of this we are using SSL but I've turned that off below to make running the sample less finicky. 注意:在此版本的生产版本中,我们使用的是SSL,但我在下面将其关闭,以减少示例的运行难度。

We set the HttpSecurityMode to TransportCredentialOnly and then the ClientCredentialType to HttpClientCredentialType.Windows which, I believe, would use Kerberos. 我们将HttpSecurityMode设置为TransportCredentialOnly,然后将ClientCredentialType设置为HttpClientCredentialType.Windows,我相信它将使用Kerberos。

If I use "NTLM" instead of "Windows" it does seem to work but I gather that using NTLM is not advised and it breaks if we have a reverse proxy sitting in front of our service. 如果我使用“ NTLM”而不是“ Windows”,它似乎可以工作,但是我认为不建议使用NTLM,并且如果在我们的服务之前有一个反向代理,它就会中断。

When we run the following code and connect in IE 10 we get do get prompted for our Windows credentials but after entering those we just get a HTTP 400 and I don't hit any breakpoints within my "Get" method. 当我们运行以下代码并连接到IE 10时,系统会提示您输入Windows凭据,但输入Windows凭据后,我们只会得到一个HTTP 400,并且在“ Get”方法中没有遇到任何断点。 Ideally what we should see is a response saying "Hello, [Domain\\User]!" 理想情况下,我们应该看到的响应是:“您好,[域\\用户]!” but we aren't making it that far. 但我们没有做到那么远。

Our testing machines (client and server) are all part of the same Windows domain. 我们的测试机(客户端和服务器)都属于同一Windows域。 I'm running the service as a local admin but not domain admin (if that would matter). 我以本地管理员而不是域管理员的身份运行服务(如果那很重要)。

We would appreciate any help! 我们将不胜感激!

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;

namespace WindowsAuthService
{
    [ServiceContract]
    public interface ITestService
    {
        [OperationContract]
        [WebGet(UriTemplate = "{*path}")]
        Stream Get(string path);
    }


    public class TestService : ITestService
    {
        public Stream Get(string path)
        {
            WebOperationContext.Current.OutgoingResponse.Headers.Add(HttpResponseHeader.ContentType, "text/plain");
            if (OperationContext.Current.ServiceSecurityContext == null)
                return new MemoryStream(Encoding.ASCII.GetBytes(String.Format("Hello, {0}!", "Anonymous Stranger")));
            else
                return new MemoryStream(Encoding.ASCII.GetBytes(String.Format("Hello, {0}!", OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name)));
        }
    }

    class Program
    {
        private const string URL = "http://mymachine.mydomain:7777";
        static void Main(string[] args)
        {
            WebServiceHost serviceHost = new WebServiceHost(new TestService());
            foreach (IServiceBehavior attr in serviceHost.Description.Behaviors)
            {
                if (attr is ServiceBehaviorAttribute)
                {
                    ServiceBehaviorAttribute serviceAttr = (ServiceBehaviorAttribute)attr;
                    serviceAttr.InstanceContextMode = InstanceContextMode.Single;
                    serviceAttr.ConcurrencyMode = ConcurrencyMode.Multiple;
                }
            }
            WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
            ServiceEndpoint serviceEndpoint = serviceHost.AddServiceEndpoint(typeof (ITestService), binding, URL);
            serviceEndpoint.Behaviors.Add(new WebHttpBehavior());
            Console.WriteLine("Service Listening @ " + URL);
            serviceHost.Open();
            Console.WriteLine("[ Press Enter to Quit ]");
            Console.ReadLine();
        }
    }
}

You've got working code. 您已经有了工作代码。 I guess you have a proxy. 我想你有代理人。 If yes, in IE 10, go to menu Tools > Internet Options > Connections (tab) > LAN Settings. 如果是,请在IE 10中转到菜单>工具> Internet选项>连接(选项卡)>局域网设置。 In the dialog, check on Bypass proxy server for local addresses. 在对话框中,在“绕过代理服务器”上检查本地地址。

Also, you can go to Security Tab > Local Intranet > Click on Sites button and choose Automatically detect local intranet - you wont be prompted for credentials - IE 10 will send credentials of logged in user. 另外,您可以转到“安全性”选项卡>“本地Intranet”>“单击站点”按钮,然后选择“自动检测本地Intranet”-不会提示您输入凭据-IE 10将发送已登录用户的凭据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM