WCF与Windows认证:选择kerberos还是NTLM
2012-11-01 17:53
381 查看
在分析一个WCF项目的过程中,遇到了一个问题,问题产生的根源在于下面的代码:
抛出的错误为:A call to SSPI failed, see inner exception.然后当我查看inner exception的时候,看到了错误信息为:The target principal name is incorrect。
开始看上去,被搞得一头雾水,根本不知道该如何去处理,不过还好,在网上看到了一篇外国文章(WCF on intranet with windows authentication: Kerberos or NTLM (Part 1) ),看完以后,按照我的理解给翻译了出来,以备后用。呵呵,我总是这么的顺手牵羊啊。
还是让我先来restore一下这个exception 发生的情形吧:
首先,我将WCF的服务器端拷贝到另外一台机器上,这台机器和我本机不在同一个网段,均处于内网中,但是通过外网相连接。
然后开启服务端,服务端总是开启一会儿就挂掉,客户端连接就会出现如上的错误。我打开系统的Event Viewer,看到了一个错误:
The kerberos client received a KRB_AP_ERR_MODIFIED error from the server host/apaccmhkap038.apac.nsroot.net. This indicates that the password used to encrypt the kerberos service ticket is different than that on the target server. Commonly, this is due to identically named machine accounts in the target realm (APAC.NSROOT.NET), and the client realm. Please contact your system administrator.
很明显啊,客户端和服务端连接的时候,采用了kerberos验证方式。但是由于验证未通过,所以抛出了错误。
这里我们肯定想问,什么是kerberos?是用来干什么的?
其实,它属于windows认证机制中的方式之一,当一台机器中的WCF程序访问另外一台机器中的资源的时候,就会发生认证申请,kerberos 和 NTLM就是这两种认证方式。二者的具体定义请参见(http://msdn.microsoft.com/en-us/library/aa480609.aspx)和(http://msdn.microsoft.com/en-us/library/aa378749(v=vs.85).aspx),
下面的图示展示了什么情况下采用哪种认证方式:
如果WCF服务端和客户端都在本机,那么采用的是NTLM认证方式,所以不会出现错误,这也是为啥我在本机同时开启的时候,能够正常运行的原因。
但是如果WCF服务端和客户端分布在不同的Domain,那么二者连接时候,认证方式则变成了kerberos。所以刚才当我将服务端放入外网的时候,在系统日志发现了当认证不匹配时kerberos错误。
在上面的代码中,我做了一点修改,加上了如下的参数:
加上以后,居然连接成功了。
这里不论我给CreateSpnIdentity任何值,程序都能够正确的运行。
所以,通过以上内容,我们的猜想如下:如果处在不同domain的服务端和客户端相互连接时,系统会首先使用机器名作为Uri,比如说,当我们连接net.tcp://remotemachine1:port/MyService的时候,WCF的客户端将会使用机器名称(EndpointIdentity.CreateSpnIdentity("remotemachine1"))作为认证的SPN,去调用service方法。当发现SPN存在但是不正确时,就转而使用NTLM认证,所以Client和Server就能连接了。当发现SPN存在并且正确时,就采用kerberos认证。当发现SPN不存在时,就直接采用kerberos认证,这也是错误出现的原因。
解决方法就是,在创建EndpointAddress的时候,加上
或者在配置文件中:
其中字串可以为任何值,这样就能使用NTLM认证,从而避免错误出现。
需要注意的是,认证发生是Client端连接Server端的时候。
EndpointAddress endPoint = new EndpointAddress(new Uri(string.Format(Constants.LocoServerBaseAddress, address) + address));
抛出的错误为:A call to SSPI failed, see inner exception.然后当我查看inner exception的时候,看到了错误信息为:The target principal name is incorrect。
开始看上去,被搞得一头雾水,根本不知道该如何去处理,不过还好,在网上看到了一篇外国文章(WCF on intranet with windows authentication: Kerberos or NTLM (Part 1) ),看完以后,按照我的理解给翻译了出来,以备后用。呵呵,我总是这么的顺手牵羊啊。
还是让我先来restore一下这个exception 发生的情形吧:
首先,我将WCF的服务器端拷贝到另外一台机器上,这台机器和我本机不在同一个网段,均处于内网中,但是通过外网相连接。
然后开启服务端,服务端总是开启一会儿就挂掉,客户端连接就会出现如上的错误。我打开系统的Event Viewer,看到了一个错误:
The kerberos client received a KRB_AP_ERR_MODIFIED error from the server host/apaccmhkap038.apac.nsroot.net. This indicates that the password used to encrypt the kerberos service ticket is different than that on the target server. Commonly, this is due to identically named machine accounts in the target realm (APAC.NSROOT.NET), and the client realm. Please contact your system administrator.
很明显啊,客户端和服务端连接的时候,采用了kerberos验证方式。但是由于验证未通过,所以抛出了错误。
这里我们肯定想问,什么是kerberos?是用来干什么的?
其实,它属于windows认证机制中的方式之一,当一台机器中的WCF程序访问另外一台机器中的资源的时候,就会发生认证申请,kerberos 和 NTLM就是这两种认证方式。二者的具体定义请参见(http://msdn.microsoft.com/en-us/library/aa480609.aspx)和(http://msdn.microsoft.com/en-us/library/aa378749(v=vs.85).aspx),
下面的图示展示了什么情况下采用哪种认证方式:
Local User | Local System | Domain User | Domain Machine | |
Local User | NTLM | NTLM | NTLM | NTLM |
Local System | Anonymous NTLM | Anonymous NTLM | Anonymous NTLM | Anonymous NTLM |
Domain User | NTLM | NTLM | Kerberos | Kerberos |
Domain Machine | NTLM | NTLM | Kerberos | Kerberos |
但是如果WCF服务端和客户端分布在不同的Domain,那么二者连接时候,认证方式则变成了kerberos。所以刚才当我将服务端放入外网的时候,在系统日志发现了当认证不匹配时kerberos错误。
在上面的代码中,我做了一点修改,加上了如下的参数:
EndpointAddress endPoint = new EndpointAddress(new Uri(string.Format(Constants.LocoServerBaseAddress, address) + address), EndpointIdentity.CreateSpnIdentity("MySystem/Service1"));
加上以后,居然连接成功了。
这里不论我给CreateSpnIdentity任何值,程序都能够正确的运行。
所以,通过以上内容,我们的猜想如下:如果处在不同domain的服务端和客户端相互连接时,系统会首先使用机器名作为Uri,比如说,当我们连接net.tcp://remotemachine1:port/MyService的时候,WCF的客户端将会使用机器名称(EndpointIdentity.CreateSpnIdentity("remotemachine1"))作为认证的SPN,去调用service方法。当发现SPN存在但是不正确时,就转而使用NTLM认证,所以Client和Server就能连接了。当发现SPN存在并且正确时,就采用kerberos认证。当发现SPN不存在时,就直接采用kerberos认证,这也是错误出现的原因。
解决方法就是,在创建EndpointAddress的时候,加上
EndpointIdentity.CreateSpnIdentity("MySPNIdentity ")
或者在配置文件中:
<endpoint name="winservicenettcp" binding="netTcpBinding" bindingConfiguration="netTcp" address="net.tcp://myserver:12345/WcfPerfTest" contract="Contract.IPerfTest" behaviorConfiguration="WcfTestBehavior"> <identity> <servicePrincipalName value="MySPNIdentity "/> </identity> </endpoint>
其中字串可以为任何值,这样就能使用NTLM认证,从而避免错误出现。
需要注意的是,认证发生是Client端连接Server端的时候。
相关文章推荐
- 一个HttpClient使用Windows认证请求WCF服务的例子
- [WCF安全系列]谈谈WCF的客户端认证[Windows认证]
- 使用 Apache Jmeter 进行 NTLM 和 Kerberos 认证
- 基于apache2和NTLM的KSS windows集成认证
- 如何选择嵌入式操作系统 Windows CE还是Windows XP Embedded?
- 如何选择嵌入式操作系统 Windows CE还是Windows XP Embedded?
- 集成验证时IE采用Kerberos 还是NTLM验证方式?(摘抄)
- 集成验证时IE采用Kerberos 还是NTLM验证方式?
- WCF简单教程(8) 安全 - Windows认证
- ASP.NET Web API系列——选择Web API还是WCF
- Windows下的身份验证----NTLM和Kerberos
- 建站选择Linux还是Windows操作系统?
- 重装系统后要选择windows 7 Loader XE 还是 windows 7
- 选择Web API还是WCF
- 网站服务器选择windows主机好还是linux主机好
- .NET Remoting过时了吗?为什么公司的项目还是选择用.NET Remoting,而不是WCF?
- [New Portal]Windows Azure Web Site (5) 如何选择Windows Azure托管服务的类型?WebSite, Cloud Service还是Virtual Machine
- 菜鸟学编程【windows程序设计】 开发工具的选择VC 6.0 还是 VC 2010
- ASP.NET Windows 验证 Part.1(简介、NTLM 验证协议、Kerberos 验证协议)
- 服务器选择Windows还是Linux