向WebService传递WindowsIdentity遇编译错误,求解决方案
解决Web服务传递WindowsIdentity的类型不匹配问题
我来帮你理清楚这个问题的原因和解决方案:
首先,你遇到的类型不匹配不是安全措施,而是SOAP Web服务(比如ASMX这类)的序列化机制导致的。当你添加Web服务引用时,Visual Studio会根据服务端的WSDL生成客户端代理类——服务端的WindowsIdentity会被解析成一个全新的、属于你的WS命名空间的WindowsIdentity类(也就是WSCommunicationTest.WS.WindowsIdentity),它和系统自带的System.Security.Principal.WindowsIdentity完全是两个不同的类型,只是字段可能类似,所以编译器会报错无法转换。
而且更关键的是:你根本没法直接传递WindowsIdentity对象。因为WindowsIdentity包含很多无法被SOAP序列化的内容,比如安全令牌的句柄、底层的安全上下文资源,这些都是不能通过XML跨进程传输的。
那该怎么处理你的需求呢?分两种情况:
1. 只是需要传递用户的身份信息(比如用户名、SID)
不要直接传WindowsIdentity,而是提取它的可序列化字段作为参数传递:
- 服务端修改方法:
[WebMethod] public void GetWI(string userSid) { // 根据SID重新构造WindowsIdentity(需要对应权限) using (WindowsIdentity wi = new WindowsIdentity(userSid)) { // 你的业务处理逻辑 } }
或者传递用户名:
[WebMethod] public void GetWI(string userName) { // 根据用户名完成身份验证或其他逻辑 }
- 客户端调用时提取对应字段:
public void Test() { WindowsIdentity wd = WindowsIdentity.GetCurrent(); WS.WStestSoapClient clt = new WS.WStestSoapClient(); // 传递用户SID clt.getWI(wd.User.Value); }
2. 需要传递当前用户的身份上下文,让服务端识别调用者身份
这时候根本不需要手动传参数,直接开启Web服务的Windows身份验证即可,客户端调用时会自动传递当前用户的Windows身份:
服务端配置(web.config)
<system.web> <!-- 启用Windows身份验证 --> <authentication mode="Windows"/> <!-- 拒绝匿名访问,确保只有授权用户能调用 --> <authorization> <deny users="?"/> </authorization> </system.web>
服务端方法直接获取身份
[WebMethod] public void GetWI() { // 直接从上下文获取当前调用者的Windows身份 WindowsIdentity wi = HttpContext.Current.User.Identity as WindowsIdentity; if (wi != null) { // 你的业务处理逻辑 } }
客户端配置(app.config/web.config)
确保绑定启用Windows身份验证:
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="WStestSoap"> <security mode="TransportCredentialOnly"> <!-- 指定使用Windows身份验证 --> <transport clientCredentialType="Windows"/> </security> </binding> </basicHttpBinding> </bindings> </system.serviceModel>
客户端调用
public void Test() { WS.WStestSoapClient clt = new WS.WStestSoapClient(); // 直接调用,身份会自动传递给服务端 clt.getWI(); }
总结一下:直接传递WindowsIdentity对象是不可行的,要么传递它的可序列化字段,要么利用Windows身份验证自动传递上下文。
内容的提问来源于stack exchange,提问作者MrHeliose
相关产品推荐
相关产品推荐

