c# - How do you restrict requests so they only work if it is accessed by a specific domain
问题描述
I have this ASP.NET Web API and I want to restrict access so it only works when called by specific host. I cannot, for what I know until now, secure it by token, because the WEB API url will be a postback url for a system that will call it automatically when a certain action is made. I have checked out CORS, but what CORS seems to do is to allow a specific domain to access the API. So, does this mean that my WEB API is already restricted for other domains? Then why I can access it by Postman locally, even if it is hosted in Azure?
I just want my service to allow calls from localhost and another specific domain only.
How do I achieve this?
Thanks!
解决方案
一种可能性是使用自定义授权过滤器,该过滤器创建一个带有失败状态代码的 HTTP 响应,如 400 bad request 或 404 not found 如果请求具有不允许的主机。我们可以定义一个如下所示的授权过滤器RestrictDomain
:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
public class RestrictDomainAttribute : Attribute, IAuthorizationFilter
{
public IEnumerable<string> AllowedHosts { get; }
public RestrictDomainAttribute(params string[] allowedHosts) => AllowedHosts = allowedHosts;
public void OnAuthorization(AuthorizationFilterContext context)
{
// Get host from the request and check if it's in the enumeration of allowed hosts
string host = context.HttpContext.Request.Host.Host;
if (!AllowedHosts.Contains(host, StringComparer.OrdinalIgnoreCase))
{
// Request came from an authorized host, return bad request
context.Result = new BadRequestObjectResult("Host is not allowed");
}
}
}
如果要RestrictDomain
全局应用过滤器,则可以在Startup.cs
文件中添加过滤器,如下所示:
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
// Add the restrict domain filter globally
// You could read the allowed hosts from a config file, here we hard code them
options.Filters.Add(new RestrictDomainAttribute("localhost", "example.com"));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
使用此设置,如果我从构造函数中删除“localhost”并且只允许“example.com”,当我使用 Postman 时会收到 400 请求,因为主机将是 localhost。
另一种选择是直接在控制器或控制器操作中使用过滤器,因为我们将其配置为作为属性工作。但是,允许的主机必须是常量值,而不是可以在运行时计算的值。这是一个例子:
using Microsoft.AspNetCore.Mvc;
[Route("")]
[ApiController]
public class HomeController : ControllerBase
{
[HttpGet]
public ContentResult Index() => Content("Home");
[HttpGet("greeting")]
[RestrictDomain("localhost", "example.com")] // values must be constants
public ContentResult Greeting() => Content("Hello, World!");
}
如果您不想要常量值并且不想全局应用过滤器,那么您可以将 注入IConfiguration
过滤器以读取可以访问资源的允许主机。
推荐阅读
- oracle - 在 Oracle APEX 的徽章列表中选择“空”值的方法
- c++ - 使用迭代器插入时的段错误
- sql - 从一个 SELECT 查询到第二个 SELECT 查询的 SQL SERVER JOIN ID 行
- c - 是否需要在 C 中的每次调用时重置信号处理程序?
- python-3.x - Pandas 与内部连接合并返回 KeyError
- c++ - 无法在 Mac OS X 上的 Visual Code 中调试 C++
- python - 带有点符号的 Pandas 列在应用期间引用索引
- javascript - 执行单击(出现检查)操作,再次执行第二次单击(检查消失)操作。需要,第二次点击删除第一个动作
- ios - 嵌入视频 Swift
- node.js - 如何在 nodejs Web 应用程序中向经过身份验证的用户发送实时通知?