将HttpContext.Current.User.Identity传递给WCF

arg*_*yle 6 authentication cookies asp.net-mvc wcf httpcontext

寻找一些建议(或者甚至是直接回答).

我有一个MVC3网站.我还有一组运行的WCF服务(现在一切都在同一个盒子里).

我正在试图做的是验证客户端(即部分工作正常),然后通过该认证的用户在各种WCF调用.

目前我已经将Application_AuthenticateRequest()方法连接起来Global.Asax,归结为创建一个新方法GenericIdentity & GenericPrincipal,然后将该主体分配给HttpContext.Current.User:

...
GenericIdentity identity = new GenericIdentity(userName);
GenericPrincipal principal = new GenericPrincipal(identity, null);
HttpContext.Current.User = principal;
...
Run Code Online (Sandbox Code Playgroud)

而那部分似乎也运作良好.

但是当我点击我的服务时,我完全失去了我设置的用户.值为空或假.

我注意到的一个主要问题是,在客户端,HttpContext.Current.User.Identity对象是类型{System.Web.Security.FormsIdentity},但在服务中它是类型{System.Security.Principal.WindowsIdentity}.

根据我读过的一些内容,听起来就像修改我的内容web.config所以它包含的内容aspNetCompatibilityEnabled="true"可能足以使其正常工作.但那不是我所看到的.所以要么我不理解一切(非常好的可能性),要么我搞砸了(另一种可能性很大).

所以我的问题.这是否可能,如果是这样的话 - 想想我错过了什么?我注意到其他一些人发布了类似的东西,但从来没有得到明确的答案(见这里这里).

任何建议都非常感谢.

Mau*_*les 2

我无法直接回答您的问题,但希望能帮助您找到明确的答案。

您有 2 个服务层,似乎您的要求是在所有层之间共享身份验证身份。

因此,原则上,您需要(至少)相同的身份验证机制或算法或技术来实现此目的。但此时你并没有使用相同的(当你看到 aFormsIdentity和 aWindowsIdentity时你注意到了)。

事实:

  • 您将需要相同的身份验证机制。
  • 无论您使用哪种机制,都需要支持您想要进行的第三跳(这意味着您可以将用户身份与第三服务一起使用,而无需实际拥有重新验证的凭据)。

问题:

  • 如果您继续使用表单身份验证,则需要使用 WCF 服务重新进行身份验证(当然还需要提供身份凭据, 可能会有所帮助)。我发现很难做到这一点,除非您保留用户用于验证他/她自己的密码,这通常是一个坏主意。
  • 如果您继续对站点使用 Windows 身份验证,那么当用户从 Intranet 登录时就会遇到问题。Kerberos(Active Directory 使用 Kerberos)的有趣之处在于,它允许用户访问远程资源而无需重新进行身份验证...但是此用户身份令牌仅适用于 1 跳。虽然您的 WCF 和 MVC 服务位于同一服务器上,但它可以工作,但如果您最终取消 WCF 服务...这是第三个框边界...第三跳,并且 Kerberos 票证将不够好。

所以...由于不知道您的要求,我首先建议您:

  • 忘记 WCF 层上的身份验证
  • 将您的 WCF 服务访问设为私有(发挥您的网络技能...防火墙等)。我首先让 WCF 在不侦听端口 80(或 443)的单独 IIS 网站上运行,并确保防火墙阻止从 LAN 外部的 IP(或者更好的是,在您的白色网络之外)访问新的 WCF 端口。列表(现在是本地主机))。
  • 将用户身份指定为每个 WCF 调用的参数。或者,如果您感到疯狂,请探索通过 SOAP 标头指定用户身份的方法(如果您的 WCF 使用 SOAP)。自定义标头也应该做得很好。您将相信您的网站能够在授予用户访问您的 WCF 服务之前正确质询和验证用户身份。

到目前为止我已经看到这个运行很多次了。不对私有服务进行身份验证是一项很好的性能交易,但您需要采取预防措施,因为一般来说,大多数 IT 攻击来自内部 LAN。