[英]How can I use Windows Authentication for Users on a ASP.NET MVC site and impersonate the user using the AppPool user on back-end WCF services?
We have a ASP.NET MVC application running on .NET 4.5.2 which is hosted on IIS 7.5 on Windows 10 or Server 2012R2. 我们有一个运行在.NET 4.5.2上的ASP.NET MVC应用程序,该应用程序托管在Windows 10或Server 2012R2的IIS 7.5上。
How can I let users sign in using their Windows accounts (using Windows Authentication Mode) and impersonate them so that the service account (configured on the App Pool) is passed through to a WCF Service instead of the original user for back-end authentication/authorization? 如何让用户使用其Windows帐户(使用Windows身份验证模式)登录并模拟它们,以便将服务帐户(在应用程序池上配置)传递给WCF服务,而不是原始用户进行后端身份验证/授权?
After some time I managed to come across an answer and solution that works. 一段时间后,我设法找到了可行的答案和解决方案。
Initially it seemed that IIS can only pass one user to the application. 最初,似乎IIS只能将一个用户传递给该应用程序。 If you open up the Configuration Editor for the MVC app and open the
system.webServer/serverRuntime
section, you will see authenticatedUserOverride
has UseAuthenticatedUser
and UserWorkerProcessUser
. 如果打开MVC应用程序的配置编辑器并打开
system.webServer/serverRuntime
部分,则将看到authenticatedUserOverride
具有UseAuthenticatedUser
和UserWorkerProcessUser
。 This will determine which user is sent to MVC and you will find the WindowsIdentity
under the User.Identity
Properties in a Controller in the MVC app. 这将确定将哪个用户发送到MVC,您将在MVC应用程序的Controller中的
User.Identity
属性下找到WindowsIdentity
。 This will not work. 这是行不通的。
I stumbled upon an article from Microsoft ( How to: Impersonate the Original Caller in WCF Calling from a Web Application ) which gave me the basis to work from which lead to the solution. 我偶然发现了Microsoft的一篇文章( 如何:从Web应用程序模拟WCF调用中的原始调用者 ),这为我提供了解决方案的基础。
In the article they make mention that you need to make use of Impersonate()
calls which looks something like this which is used on the client side: 他们在文章中提到需要使用
Impersonate()
调用,该调用看起来像在客户端使用的样子:
using (((WindowsIdentity)User.Identity).Impersonate())
{
var channelFactory = new ChannelFactory<IService1>("*");
var proxy = channelFactory.CreateChannel();
return View((object)proxy.GetName("1"));
}
On the service side you need to mark your operations for Impersonation: 在服务方面,您需要标记要模拟的操作:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
I also added the PrincipalPermission
to make sure that only the service account comes through: 我还添加了
PrincipalPermission
,以确保只有服务帐户才能通过:
[PrincipalPermission(SecurityAction.Demand, Name = "PC-NAME\\SvcAccount")]
And it seems that you need to make use of the wsHttpBinding
binding. 似乎您需要利用
wsHttpBinding
绑定。
<wsHttpBinding>
<binding name="secure">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
I got it to work over SSL and it passed credentials through automatically to the WCF service but it was the original user instead of the service account, so I got authorization errors coming from the service. 我使它可以通过SSL进行工作,并且它自动将凭据传递给WCF服务,但它是原始用户而不是服务帐户,因此我收到了来自服务的授权错误。
Upon further googling I found this snippet which gave me an idea: Getting NetworkCredential for current user (C#) 进一步谷歌搜索后,我发现了这个片段,这给了我一个主意: 为当前用户获取NetworkCredential(C#)
I substituted my client code to look like this: 我将客户代码替换为如下形式:
using (System.Security.Principal.WindowsIdentity.GetCurrent().Impersonate())
{
var channelFactory = new ChannelFactory<IService1>("*");
var proxy = channelFactory.CreateChannel();
return View((object)proxy.GetName("1"));
}
Then lo and behold! 然后瞧瞧! It worked!
有效! Service authorized the user (I changed the name in the attribute just to make sure I wasn't dreaming) and returned a value and the front-end UI still showed the logged in user.
服务授权了该用户(我更改了属性的名称,以确保我没有做梦)并返回一个值,并且前端UI仍显示已登录的用户。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.