我有一个简单的ASP.Net Core 2.1 MVC应用程序,并且在其中一个控制器中,我想实现一个仅接受本地请求的操作(即,请求源自127.0.0.1或与该地址相同的地址)服务器的IP)。
我一直在ASP.Net Core中寻找一种适合此目的的过滤器,但似乎找不到。我可以使用AuthorizeAttribute,例如[Authorize(Policy = "LocalOnly")]
并在启动中的ConfigureServices中注册相应的策略:
services.AddAuthorization(options =>
{
options.AddPolicy("LocalOnly", policy =>
{
policy.RequireAssertion(context =>
{
if (context.Resource is AuthorizationFilterContext mvcContext)
{
return mvcContext.HttpContext.Request.IsLocal();
}
return false;
});
});
});
其中IsLocal()
是HttpRequest
的扩展方法。
但是,我认为这不是正确的方法-我试图做的实际上不是授权,并且由于我的程序中没有身份验证,因此产生的错误是不正确的要么。
是否有一种简单合法的方法来完成我想要的过滤器?还是这实际上应该在控制器的动作逻辑中完成?还是整个检查本地请求的想法不是很正确?
非常感谢您的帮助。
答案 0 :(得分:1)
用作ASP.NET Core中间件。
在最简单的情况下,使用app.Use(...)
方法。
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
if (context.Request.IsLocal())
{
// Forbidden http status code
context.Response.StatusCode = 403;
return;
}
await next.Invoke();
});
}
}
委托调用根据本地请求返回,从而在此处停止中间件管道。
但是我不确定100%是否要归档。
您是否只想从内部网络调用该服务?更简单的方法是使用docker容器,将需要相互通信的服务添加到同一网络,并且仅将应用程序暴露在确实需要与外界通信的容器外部。
答案 1 :(得分:0)
IsLocal()
的扩展方法应如下所示:
public static class HttpRequestExtensions
{
public static bool IsLocal(this HttpRequest req)
{
var connection = req.HttpContext.Connection;
if (connection.RemoteIpAddress != null)
{
if (connection.LocalIpAddress != null)
{
return connection.RemoteIpAddress.Equals(connection.LocalIpAddress);
}
else
{
return IPAddress.IsLoopback(connection.RemoteIpAddress);
}
}
// for in memory TestServer or when dealing with default connection info
if (connection.RemoteIpAddress == null && connection.LocalIpAddress == null)
{
return true;
}
return false;
}
}
要确定请求是否是本地的,我们可以检查连接上的RemoteIpAddress
和LocalIpAddress
是否相同,或者如果由于某些原因而未知本地IP,请检查{{ 1}}是回送地址。
您可以在strathweb文章中了解有关此内容的更多信息。
请注意,如果使用RemoteIpAddress
,它将不起作用。
如果您确实希望它起作用,请将其更改为:
connection.RemoteIpAddress == "::1"