2016-08-25 3 views
0

У меня есть ASP.NET MVC WebApplication, размещенный в server-frontend, который является клиентом приложения WCF, размещенного в server-wcf, как в той же сети/домене. Оба сервера - это Windows Server 2012 с IIS 8.Получить имя пользователя вызывающего абонента вместо имени компьютера в WCF

Я включил проверку подлинности Windows и отключил ее в обоих проектах (csproj).

Если я называю this.User.Identity.Name внутри контроллера в моем WebApp, он правильно дает пользователю авторизованы (например MYDOMAIN \ Alisson).

Оба проекта были настроены с проверкой подлинности Windows в IIS, и WebApp, в частности, имеет олицетворение ASP.NET. Оба имеют формы, основные и анонимные отключены. В обоих пулах используется NetworkService.

Мой проект WCF отвечает за подключение к SQL Server, и он работает правильно, поскольку я дал разрешение самому компьютеру в моей базе данных (например, server-wcf$), и это именно то, что я ожидаю.

Теперь я пытаюсь вызвать метод WCF из моего WebApp так:

var binding = new BasicHttpBinding(); 
binding.MaxReceivedMessageSize = 10485760; 
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; 
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; 

var endPoint = new EndpointAddress(address); 
var channelFactory = new ChannelFactory<IMyService>(binding, endPoint); 
var client = channelFactory.CreateChannel(); 
client.GetUser(); 

и это GetUser() в моей службы WCF объявляется следующим образом:

public GetUser() 
{ 
    return ServiceSecurityContext.Current.WindowsIdentity.Name; 
} 

который возвращает domain\server-frontend вместо от domain\alisson.

Я хочу, чтобы он получил пользователя в WCF, но поддерживайте способ подключения WCF к базе данных как к самому себе (server-wcf).

Мои WebApp web.config имеет следующее:

<identity impersonate="true" /> 
<authentication mode="Windows" /> 
<authorization> 
    <deny users="?" /> 
</authorization> 

В то время как WCF имеет следующий внутри web.config ServiceModel:

<bindings> 
    <basicHttpBinding> 
    <binding name="AutomatizacaoBinding" maxReceivedMessageSize="10485760"> 
     <security mode="TransportCredentialOnly"> 
     <transport clientCredentialType="Windows" /> 
     </security> 
    </binding> 
    </basicHttpBinding> 
</bindings> 
<protocolMapping> 
    <add binding="basicHttpsBinding" scheme="https" /> 
</protocolMapping> 
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 

Можно ли добиться этого?

ответ

0

Вы должны использовать вместо OperationContext:

return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name; 

Примечание: если интегрированная защита не включена, ServiceSecurityContext будет нулевым.

Надеюсь, это поможет.

+0

Это то же самое, что и 'ServiceSecurityContext.Current.WindowsIdentity.Name'. Я хотел получить то же самое, что вызвать 'this.User.Identity.Name' в caller WebApp Controller, который возвращает' domain \ alisson'. – Alisson

+0

Собственно, это возвращает ** domain \ alisson **, только если я запускаю WebApp локально в VS с помощью IIS Express. Когда я публикую его на своем «сервере-frontend», он получает ** domain \ server-frontend ** в качестве идентификатора. – Alisson

+0

У меня есть аналогичная служба, которая отлично работает с OperationContext, но из-за вашего комментария я заметил, что существует небольшая разница между нашими конфигурационными файлами, мой набор «режим безопасности» как «Транспорт», а не «TransportCredentialOnly», возможно это может сделать некоторую разницу –

0

Это очень возможно, но не так просто.

Возможно, вы сможете просто получить имя вызывающего абонента, но не восстановить его идентификатор. Так как навсегда, вы должны использовать Negotiate/Kerberos Security для more than one jump между машинами при восстановлении тождеств.

В действительности очень скучно, поскольку для тестирования не всегда доступен сервер Active Directory (я должен создавать тестовые учетные записи в рабочей среде на моем месте). Neg/Kerberos - это старая технология, которую я использую большую часть времени, хотя есть несколько предостережений с SPN и CNAME (не используйте CNAMES, используйте A-records).

Другой альтернативой является использование более новой технологии, такой как ADFS, которая проходит вокруг какого-то огромного претендента cookie, называемого федерацией, но все зависит от того, как выглядит ваша производственная среда.

Как только это будет установлено, тот или другой. Если вы хотите, чтобы WCF продолжал делать звонки как сам, просто держите свой код и не настраивайте какое-либо неявное олицетворение. Вы все равно можете получить личность, если в большинстве случаев вы будете искать запрос wcf.

Если вы хотите на самом деле изобразить себя, откройте impersonation scope. Повторяя ближе к примеру, следующее не будет работать, если вы сначала не настроите Kerberos или adfs.

using System.Security.Principal; 
using(WindowsIdentity.GetCurrent().Impersonate()) 
{ 
    //your code goes here, executed as domain\alisson 
} 
+0

Я думал, что ADFS должен был сделать разные домены для обмена/совместного использования учетных данных, в моем случае оба сервера находятся в одном домене, я никогда не думал, что это может помочь как-то. Я собираюсь прочитать эти подходы и дать некоторые отзывы. – Alisson

+0

Я знаю, что adfs может решить две проблемы с прыжком, в теории проще, чем kerberos, но я никогда не использовал его сам в производственном коде, поэтому я не знаю. Как вы говорите, если вы находитесь в нескольких доменах, предпочтительнее adfs. kerberos - это метод перехода на идентификацию окон, это старая и проверенная технология. Например, ntlm работает только для одного машинного скачка. Браузер для сервера считается одним прыжком, поэтому с ntlm вы застряли на веб-сервере. – Tewr