Вот решение, к которому мы пришли.Это было частично основано на рекомендациях нашего представителя Microsoft, поэтому вы можете считать это неофициальным, «официальным» подходом.
Во-первых, нам нужно не допустить, чтобы SharePoint рекламировал файл дискотеки Мир (то есть Google).Просто удалите следующую строку на своих главных страницах:
<SharePoint:SoapDiscoveryLink runat="server"/>
Это исключит ссылку <link href="/_vti_bin/spsdisco.aspx" rel="alternate" type="text/xml">
в заголовке ваших страниц.
Далее мы хотим убедиться, что неавторизованные пользователиу меня нет доступа к веб-службам, описанным в файле диско, или к чему-либо в _vti_bin
.Если ваш сайт работает только внутри вашего брандмауэра (например, в интрасети), это не так важно.Но если у вас есть анонимные конечные точки, к которым можно получить доступ извне, вы хотите, чтобы они были заблокированы.
Это отличное приложение для HttpModule .Мы создадим тот, который перехватывает любой запрос, содержащий _vti_bin
в пути, и если текущий пользователь не авторизован, вернет код состояния 404 NOT FOUND
.Я решил вернуть 404, а не 401 UNAUTHORIZED
, потому что я не просто хочу заблокировать эти пути, я хочу скрыть тот факт, что что-то даже существует на этих путях.
Наш HttpModule выглядит следующим образом:
using System;
using System.Web;
namespace Custom.SharePoint.HttpModule.SpSecureVtiBin {
public class SpSecureVtiBinModule : IHttpModule {
#region IHttpModule Members
public void Dispose() { }
public void Init( HttpApplication context ) {
context.AuthorizeRequest += new EventHandler( context_AuthorizeRequest );
}
protected virtual void context_AuthorizeRequest( object sender, EventArgs e ) {
HttpApplication app = (HttpApplication)sender;
string requestedPath = app.Request.Path;
if ( requestedPath.ToLowerInvariant().Contains( "_vti_bin" ) ) {
if ( !app.Request.IsAuthenticated ) {
app.Response.StatusCode = 404;
app.Response.StatusDescription = "Not Found";
app.Response.Write( "404 NOT FOUND" );
app.Response.End();
}
}
}
#endregion
}
}
Достаточно просто.Чтобы использовать HttpModule, его необходимо зарегистрировать в файле web.config сайта с записью под \configuration\system.webServer\modules
:
<add name="SpSecureVtiBinModule" type="Custom.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule, Custom.SharePoint.HttpModule.SpSecureVtiBin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[your_public_key_token]" />
Конечно, мы не хотим изменятьфайл web.config приложения SharePoint вручную.Мы создадим SPFeatureReceiver для выполнения этой работы:
using System.Collections.ObjectModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace Custom.SharePoint.HttpModule.SpSecureVtiBin {
public class ModuleFeatureReceiver : SPFeatureReceiver {
private static string _owner = "SpSecureVtiBinModule";
public override void FeatureActivated( SPFeatureReceiverProperties properties ) {
SPWebApplication app = (SPWebApplication)properties.Feature.Parent;
app.WebConfigModifications.Add( GetModificationForSystemWebServer() );
app.WebService.ApplyWebConfigModifications();
app.Update();
}
public override void FeatureDeactivating( SPFeatureReceiverProperties properties ) {
SPWebApplication app = (SPWebApplication)properties.Feature.Parent;
Collection<SPWebConfigModification> mods = app.WebConfigModifications;
int modCount = mods.Count;
bool modRemoved = false;
for ( int i = modCount - 1; i >= 0; i-- ) {
SPWebConfigModification mod = mods[i];
if ( mod.Owner.Equals( _owner ) || mod.Owner.Equals( "CHK.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule" ) ) {
app.WebConfigModifications.Remove( mod );
modRemoved = true;
}
}
if ( modRemoved ) {
app.WebService.ApplyWebConfigModifications();
app.Update();
}
}
private SPWebConfigModification GetModificationForSystemWebServer() {
return new SPWebConfigModification {
Name = "add[@name='SpSecureVtiBinModule']",
Owner = _owner,
Path = "configuration/system.webServer/modules",
Value = @"<add name=""SpSecureVtiBinModule"" type=""Custom.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule, Custom.SharePoint.HttpModule.SpSecureVtiBin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[your_public_key_token]"" />",
Sequence = 0
};
}
}
}
Теперь осталось только упаковать HttpModule.Вам необходимо определить функцию в пакете и ссылаться на класс SPFeatureReceiver.Это приведет к тому, что запись web.config будет добавлена, когда функция будет активирована, и запись будет удалена, когда функция будет деактивирована.Настройте компонент для WebApplication
и цель развертывания сборки на GlobalAssemblyCache
.