Thread.CurrentPrincipal не установлен в службе WCF, вызванной с помощью WebGet
У меня есть веб-сайт, размещенный в IIS, который использует проверку подлинности Windows и предоставляет веб-службы WCF.
Я настраиваю эту службу с помощью поведения конечной точки:
<serviceAuthorization principalPermissionMode ="UseAspNetRoles"
roleProviderName="MyRoleProvider"/>
и привязка:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
При вызове службы Thread.CurrentPrincipal
устанавливается в RolePrincipal
с идентификатором клиента и ролями, предоставленными сконфигурированным поставщиком.
Все хорошо с миром.
Теперь я добавил несколько дополнительных 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?
UPDATE
Вот блог от кого-то, у кого была такая же проблема, и решил его, внедряя пользовательские поведения. Наверняка есть способ сделать это из коробки?
ОБНОВЛЕНИЕ 2
Возвращаясь назад, чтобы добавить щедрость к этому, поскольку он снова прослушивает меня в новом проекте, используя службу WCF WebGet с поддержкой .NET 3.5.
Я экспериментировал с несколькими параметрами, включая настройку mainPermissionMode = "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? Если у меня есть mainPermissionMode = "UseAspNetRoles", конечно, WCF должен знать, что мне нужно?
Ответы
Ответ 1
Это интересный вопрос. У меня нет такой же настройки, как у вас, поэтому трудно проверить, будут ли мои рекомендации применяться именно к вашему прецеденту, но я могу поделиться тем, что сработало для нас с похожими проектами.
Как мы сохраняем Thread.CurrentPrincipal
и HttpContext.Current.User
в Sync
Мы написали 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 для проверки подлинности форм, расшифровываем его и т.д.... вам может понадобиться выполнить ping некоторые встроенные методы для WindowsAuthentication.
Я считаю, что это более общий способ обработки ваших файлов аутентификации приложений, поскольку он применяется ко всем HttpRequests
, будь то запрос страницы, IHttpHandler
, какой-то сторонний компонент и т.д.... Это будет поддерживать его последовательно в вашем приложении.
Ответ 2
Я не уверен. Возможно, это поможет
<configuration>
<system.web>
<identity impersonate="true" />
</system.web>
</configuration>
http://msdn.microsoft.com/en-us/library/134ec8tc(v=vs.80).aspx