You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

REST API能否仅允许前端域名调用?安全问题咨询

问题描述
  • 前端采用Angular框架,部署地址:https://dev.myApp.com/
  • 后端为.NET 8 REST API,部署地址:https://dev.dataAPI.com/api/
  • 前端调用API的代码:
data(): Observable<Response> {
    const path = `${this._apiUrl}/Parameter/Data`;
    return this._http.get<Response>(path);
}
  • API返回内容:
{
    "success": 1,
    "message": "Ok",
    "data": [
        {
            "id": 27,
            "descri": "URUGUAY"
        }
    ]
}
  • 当前API的CORS配置(.NET 8):
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("CorsApi",
        builder => builder.WithOrigins("*")
    .AllowAnyHeader()
    .AllowAnyMethod());
});

核心疑问:

  1. 直接在浏览器中访问该GET请求的完整URL也能获取数据,这种情况是否属于正常行为?
  2. 是否可以让API验证调用来源,拒绝非我方APP发起的请求?当前未使用Token等安全机制,需要临时方案,且担心CORS容易被绕过。
问题解答

1. 这种情况是否正常?

这是完全正常的行为。你的API当前配置了允许所有来源(WithOrigins("*")),且没有任何身份验证或来源校验逻辑,所以任何客户端(包括浏览器地址栏直接访问、Postman等工具)都能调用该接口。

另外要明确:CORS是浏览器端的安全机制,它只限制浏览器中运行的前端脚本发起跨域请求,不会阻止绕开浏览器脚本环境的请求(比如地址栏直接访问、工具调用)。这就是你觉得“CORS容易被绕过”的核心原因——它从设计上就不是用来做服务器端来源校验的。

2. 如何让API验证调用来源,拒绝非我方APP的请求?

如果暂时不想用Token这类完整身份验证方案,可以尝试以下临时方案,但要注意它们都有局限性,不能替代正式的安全机制:

(1)严格CORS配置 + 请求头校验

首先修改CORS规则,只允许你的前端域名访问,替换掉通配符:

builder.Services.AddCors(options =>
{
    options.AddPolicy("CorsApi",
        builder => builder.WithOrigins("https://dev.myApp.com")
                          .AllowAnyHeader()
                          .AllowAnyMethod());
});

然后在API中间件中手动校验Origin或Referer请求头:

app.Use(async (context, next) =>
{
    var allowedOrigin = "https://dev.myApp.com";
    var origin = context.Request.Headers.Origin.FirstOrDefault();
    var referer = context.Request.Headers.Referer.FirstOrDefault();

    // 校验请求来源是否为允许的域名
    if (!string.IsNullOrEmpty(origin) && origin != allowedOrigin 
        || !string.IsNullOrEmpty(referer) && !referer.StartsWith(allowedOrigin))
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        await context.Response.WriteAsync("Invalid request origin");
        return;
    }

    await next();
});

局限性:Origin和Referer头极易被伪造,只能拦截浏览器中其他网站的脚本请求,无法阻止刻意伪造的请求。

(2)自定义请求头校验

在前端请求中添加自定义请求头,比如X-App-Key:

data(): Observable<Response> {
    const path = `${this._apiUrl}/Parameter/Data`;
    const headers = new HttpHeaders().set('X-App-Key', 'your-custom-secret-key');
    return this._http.get<Response>(path, { headers });
}

然后在API中校验该请求头的有效性:

app.Use(async (context, next) =>
{
    const validAppKey = "your-custom-secret-key";
    if (!context.Request.Headers.TryGetValue("X-App-Key", out var appKey) 
        || appKey != validAppKey)
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        await context.Response.WriteAsync("Invalid app key");
        return;
    }

    await next();
});

局限性:前端的密钥可以通过浏览器开发者工具被查看到,仅能拦截非刻意的非法请求,不适合长期使用。

(3)IP白名单(仅内部部署场景可用)

如果前端和后端都在内部网络,且前端服务器IP固定,可以配置API只允许该IP访问:

app.Use(async (context, next) =>
{
    var allowedIp = "192.168.1.100"; // 替换为前端服务器实际IP
    var clientIp = context.Connection.RemoteIpAddress?.ToString();

    if (clientIp != allowedIp)
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        await context.Response.WriteAsync("Invalid IP address");
        return;
    }

    await next();
});

局限性:如果前端面向公网用户,用户IP动态变化,该方案完全不可行;且IP也可通过代理伪造。

总结

以上临时方案仅能作为过渡,长期来看必须使用正式的身份验证机制(比如JWT Token、OAuth2等),才能真正保障API的访问安全。

内容的提问来源于stack exchange,提问作者FranciscoFJM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:53:13