#c# #asp.net-core
#c# #asp.net-ядро
Вопрос:
В обычном ASP.NET вы могли бы сделать это в представлении, чтобы определить, был ли текущий запрос от localhost:
HttpContext.Current.Request.IsLocal
Но я не могу найти что-то подобное в ASP.NET 6/Ядро/ как бы оно ни называлось.
Комментарии:
1. Будьте осторожны с использованием
HttpContext.Connection.IsLocal
. Мне кажется, что использованиеHttpContext.Connection.RemoteIpAddress
является более безопасным способом . Если я подключусь к тестированию ASP.NET 5 Проект RC1 локально я вижу::1
вRemoteIpAddress
, ноHttpContext.Connection.IsLocal
естьfalse
. Это неправильно.2. Приветствую Олег, то, что вы сказали, оказалось правдой и для меня.
3. Я тоже получаю такое же поведение. Это всегда
false
локально.
Ответ №1:
ОБНОВЛЕНИЕ: ASP.NET В ядре 2.0 есть метод с именем Url.IsLocalUrl
(см. Этот документ Microsoft Docs).
Я думаю, что этот код будет работать, но я не смог протестировать его полностью
var callingUrl = Request.Headers["Referer"].ToString();
var isLocal = Url.IsLocalUrl(callingUrl);
Но смотрите Комментарий Уилла Дина ниже об этом подходе:
Любой, кто думает об использовании «обновленной» версии, которая проверяет заголовок ссылки, должен иметь в виду, что заголовки чрезвычайно легко подделать до такой степени, что это не относится к IP-адресам с обратной связью.
Оригинальное решение
Я наткнулся на это в поисках решения, позволяющего узнать, является ли запрос локальным. К сожалению ASP.NET версия 1.1.0 не имеет IsLocal
метода для подключения. Я нашел одно решение на веб-сайте под названием Strathweb, но оно тоже устарело.
Я создал свое собственное IsLocal
расширение, и оно, кажется, работает, но я не могу сказать, что тестировал его во всех обстоятельствах, но вы можете попробовать.
public static class IsLocalExtension
{
private const string NullIpAddress = "::1";
public static bool IsLocal(this HttpRequest req)
{
var connection = req.HttpContext.Connection;
if (connection.RemoteIpAddress.IsSet())
{
//We have a remote address set up
return connection.LocalIpAddress.IsSet()
//Is local is same as remote, then we are local
? connection.RemoteIpAddress.Equals(connection.LocalIpAddress)
//else we are remote if the remote IP address is not a loopback address
: IPAddress.IsLoopback(connection.RemoteIpAddress);
}
return true;
}
private static bool IsSet(this IPAddress address)
{
return address != null amp;amp; address.ToString() != NullIpAddress;
}
}
Вы вызываете его в действии контроллера, используя Request
свойство, т.е.
public IActionResult YourAction()
{
var isLocal = Request.IsLocal();
//... your code here
}
Я надеюсь, что это кому-то поможет.
Комментарии:
1. Это помогло мне. Вот моя версия.
2. Любой, кто думает об использовании «обновленной» версии, которая проверяет заголовок ссылки, должен иметь в виду, что заголовки чрезвычайно легко подделать, до такой степени, что это не относится к IP-адресам с обратной связью.
3. Заголовок
Referer
запроса не имеет никакого отношения к тому, является ли удаленный IP-адрес локальным или нет.
Ответ №2:
На момент написания HttpContext.Connection.IsLocal
в настоящее время отсутствует в .NET Core.
Другое рабочее решение проверяет только первый адрес обратной связи ( ::1
или 127.0.0.1
), который может быть неадекватным.
Я нахожу приведенное ниже решение полезным:
using Microsoft.AspNetCore.Http;
using System.Net;
namespace ApiHelpers.Filters
{
public static class HttpContextFilters
{
public static bool IsLocalRequest(HttpContext context)
{
if (context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
{
return true;
}
if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress))
{
return true;
}
return false;
}
}
}
И пример использования:
app.UseWhen(HttpContextFilters.IsLocalRequest, configuration => configuration.UseElmPage());
Комментарии:
1. Этот метод можно упростить до
public static bool IsLocalRequest(HttpContext context) => context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress) || IPAddress.IsLoopback(context.Connection.RemoteIpAddress);
.2. Разве 2-й
if
не должен читатьif (IPAddress.IsLoopback(context.Connection.LocalIpAddress))
вместо использованияRemoteIpAdress
?3. Я не думаю, что это имеет значение на практике, функция может возвращать false, если кто-то устанавливает соединение с адресом внешнего интерфейса из loopback или наоборот, но это не то, что происходит по умолчанию, поэтому любой IP-адрес из диапазона 127 или IPv6 будет принят независимо от того, является ли он удаленным контрольный или местный. Кроме того, поскольку проверка касается удаленного подключения к серверу, проверка удаленного адреса лучше подходит для этой цели.
4. Можно ли это подделать?
Ответ №3:
Для меня ничего из вышеперечисленного не сработало.
Url.IsLocalUrl работает совсем по-другому, и я нахожу это немного бесполезным:
Например, следующие URL-адреса считаются локальными:
/Views/Default/Index.html
~/Index.html
Следующие URL-адреса являются нелокальными:
../Index.html
http://www.contoso.com/
http://localhost/Index.html
HttpContext.Connection.IsLocal
не существует в .Net Core 2.2
Сравнение ControllerContext.HttpContext.Connection.RemoteIpAddress
и ControllerContext.HttpContext.Connection.LocalIpAddress
также не работает в моем тесте, потому что я получаю «:: 1» для удаленного ip и «127.0.0.1» для локального ip.
Наконец, я использовал эту часть:
IPAddress addr = System.Net.IPAddress.Parse( HttpContext.Connection.RemoteIpAddress.ToString() );
if (System.Net.IPAddress.IsLoopback(addr) )
{
//do something
}
Ответ №4:
Поздно на вечеринку, но если я хочу проверить IsLocal в представлениях razor.Net core 2.2 , я просто делаю это:
@if (Context.Request.Host.Value.StartsWith("localhost"))
{
//do local stuff
}
Комментарии:
1. Это очень уродливый способ сделать это. Что, если у вас есть сайт под названием localhost.site.com ? Или даже localhosting.com .
Ответ №5:
ОБНОВЛЕНИЕ для ASP.NET Ядро 3.1
Вы можете использовать это:
if (Request.Host.Host == "localhost") {// do something }
Ответ №6:
Я также хотел бы упомянуть, что может быть полезно добавить предложение ниже в конец вашей пользовательской IsLocal()
проверки
if (connection.RemoteIpAddress == null amp;amp; connection.LocalIpAddress == null)
{
return true;
}
Это учитывало бы сценарий, в котором сайт запускается с использованием Microsoft.AspNetCore.TestHost
, и сайт запускается полностью локально в памяти без фактического TCP / IP-соединения.
Ответ №7:
теперь его
HttpContext.Connection.IsLocal
и если вам нужно проверить это вне контроллера, тогда вы получаете зависимость IHttpContextAccessor
, чтобы получить к нему доступ.
Обновление на основе комментариев:
HttpContext
внутренне доступен в представлениях
@if (Context.Connection.IsLocal)
{
}
Комментарии:
1. Я беру зависимость в представлении, делая это
@inject IHttpContextAccessor Context;
правильно? Текущее значение local всегда равно false…2. Это уходит в RC2. У Филипа здесь есть альтернативный подход: strathweb.com/2016/04/request-islocal-in-asp-net-core но даже это, похоже, сильно зависит от другого промежуточного программного обеспечения и от того, какой сервер вы используете.