Thread.CurrentPrincipal не установлен в службе WCF, вызываемой с помощью WebGet - PullRequest
12 голосов
/ 27 января 2012

У меня есть веб-сайт, размещенный в IIS, который использует проверку подлинности Windows и предоставляет веб-службы WCF.

Я настраиваю эту службу с поведением конечной точки:

<serviceAuthorization principalPermissionMode ="UseAspNetRoles" 
                   roleProviderName="MyRoleProvider"/>

и привязкой:

 <security mode="TransportCredentialOnly">
    <transport clientCredentialType="Ntlm" />
 </security>

Когда вызывается служба, Thread.CurrentPrincipal устанавливается на RolePrincipal с идентификатором Windows клиента и ролями, предоставленными настроенным провайдером.

Все в порядке с миром.

Теперь я добавил несколько дополнительных служб WCF, которые используются вызовами REST-ful Ajax: Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" в файле svc, атрибут WebGet в контракте на обслуживание и атрибут AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed) вреализация службы.

Я также добавляю следующее заклинание в web.config, как рекомендовано в MSDN:

<system.serviceModel>
    ...
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    ...
</system.serviceModel>

Моя служба Ajax почти работает так, как я хочу,Когда он вызывается, HttpContext.Current.User устанавливается на RolePrincipal с ролями, которые я ожидаю.Но Thread.CurrentPrincipal остается установленным без проверки подлинности GenericPrincipal.

Поэтому мне нужно добавить строку кода для каждого из моих методов обслуживания:

Thread.CurrentPrincipal = HttpContext.Current.User

Есть ли какие-либо заклинания вфайл конфигурации, который я могу использовать для автоматической установки Thread.CurrentPrincipal, как для обычной службы SOAP?

ОБНОВЛЕНИЕ Вот блог от кого-то, у кого былта же проблема, и решил ее путем реализации пользовательских поведений.Конечно, есть способ сделать это из коробки?

ОБНОВЛЕНИЕ 2 Возвращаясь, чтобы добавить награду к этому, поскольку это снова вызывает меня в новом проекте, используя WCF с поддержкой WebGetСлужба в .NET 3.5.

Я экспериментировал с рядом опций, включая установку PrincipalPermissionMode = "None", но ничего не работает.Вот что происходит:

  • Я перехожу на URL WebGet, который вызывает мою службу: http://myserver/MyService.svc/...

  • Я установил точку останова в Global.asax "Application_AuthorizeRequest".Когда достигается эта точка останова, для обоих «HttpContext.Current.User» и «Thread.CurrentPrincipal» устанавливается значение «RolePrincipal», в котором используется мой настроенный ASP.NET RoleProvider.Это поведение, которое я хочу.

  • У меня есть вторая точка останова, когда вызывается метод OperationContract моей службы.При достижении этой точки останова HttpContext.Current.User по-прежнему ссылается на мой RolePrincipal, но Thread.CurrentPrincipal был изменен на GenericPrincipal.Aaargh.

Я видел предложения реализовать пользовательскую IAuthorizationPolicy , и рассмотрим это, если я не найду лучшего решения, но почему я долженВам нужно реализовать собственную политику для использования существующих функций авторизации ASP.NET?Если у меня есть PrincipalPermissionMode = "UseAspNetRoles", конечно, WCF должен знать, что я хочу?

Ответы [ 2 ]

6 голосов
/ 17 октября 2012

Это интересный вопрос. У меня нет такой же настройки, как у вас, поэтому сложно проверить, будут ли мои рекомендации в точности соответствовать вашему варианту использования, но я могу поделиться тем, что сработало для нас в подобных проектах.

Как мы сохраняем Thread.CurrentPrincipal и HttpContext.Current.User в синхронизации

Мы написали HttpModule под названием «AuthenticationModule», который наследуется от IHtppModule.

Затем мы присоединяемся к событию HttpApplication.AuthenticateRequest, которое происходит очень рано в жизненном цикле запроса.

В нашем обработчике событий AuthenticateRequest мы реализуем особые требования нашего приложения, включая настройку Thread.CurrentPrincipal и, при необходимости, также текущего пользователя контекста. Таким образом, вы реализуете этот код только один раз для всего вашего приложения, и если он изменяется (например, если вы реализуете пользовательский основной IIDentity), у вас есть только одно место, чтобы изменить его. (Не дублируйте этот код в каждом методе обслуживания.)

public class AuthenticationModule : IHttpModule
{
    public void Dispose() { return; }

    public void Init(HttpApplication app)
    {
        app.AuthenticateRequest += new EventHandler(app_AuthenticateRequest);
    }

    void app_AuthenticateRequest(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;

        // This is what you were asking for, but hey you 
        // could change this behavior easily.
        Thread.CurrentPrincipal = app.Context.User;
    }
}

У нас на самом деле все немного сложнее, так как мы реализуем пользовательский IIdentity, создаем экземпляр GenericPrincipal и затем присваиваем его обоим app.Context.User и Thread.CurrentPrincipal; но то, о чем вы просили, было выше.

Не забудьте зарегистрировать свой новый HttpModule в web.config!

Для интегрированных пулов приложений:

<system.webServer>
    <modules>
      <add name="AuthenticationModule" type="YourNameSpace.AuthenticationModule" preCondition="integratedMode" />
    </modules>
</system.webServer>

Для старых классических пулов приложений вы должны поместить его в <system.web><httpModules></httpModules></system.web>

Возможно, вам придется поиграть с тем, что происходит внутри этого обработчика события AuthenticationRequest и / или с порядком, в котором вы регистрируете обработчик. Потому что у нас совершенно обычай, это может отличаться от того, что вам нужно. На самом деле мы получаем cookie-файл проверки подлинности с помощью форм, расшифровываем его и т. Д., Возможно, вам потребуется пропинговать некоторые встроенные методы для проверки подлинности Windows.

Я полагаю, что это более общий способ обработки аутентификации вашего приложения, поскольку он применяется ко всем HttpRequests, будь то запрос страницы, IHttpHandler, какой-либо сторонний компонент и т. Д. ... Это сохранит его согласованно во всем приложении.

1 голос
/ 12 октября 2012

Я не уверен. Может быть, это поможет

<configuration>
  <system.web>
    <identity impersonate="true" />
  </system.web>
</configuration>

http://msdn.microsoft.com/en-us/library/134ec8tc(v=vs.80).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...