asp.net 在外部使用者(应用程序)中使用API防伪令牌而不进行身份验证

v9tzhpje  于 2023-03-05  发布在  .NET
关注(0)|答案(3)|浏览(134)

如何在ASP.NET Core 6 Web API中将防伪令牌用于iOS或Android应用程序等外部消费者?我不需要对请求进行用户身份验证。应用程序托管在另一个域上。
我已经开发了一个Web API与防伪令牌(按照此链接)和ASP.NET 6剃刀页。所有的工作perfekt。但我怎么能开发一个外部应用程序使用此Web API?问题是,我不知道我怎么能创建防伪令牌从“外部”应用程序?我怎么能配置应用程序使用Web API与防伪令牌?

bnl4lu3b

bnl4lu3b1#

在构建API时,不必针对CSRF攻击实施防伪令牌保护,因为API是如何构建和使用的,它们需要不同的保护方法,例如:

  • 使用API密钥。
  • 使用基本身份验证。
  • 使用OpenID连接。

因为目标是防止恶意客户端调用我们的API,所以我们需要验证执行API请求的客户端应用程序的身份。
要执行CSRF攻击,一个主要条件是具有基于Cookie的身份验证会话(请参阅article,其中详细解释了如何执行CSRF攻击),而API则不是这种情况。
但是,如果您使用 AJAX 从您的网站调用API,其中API与网站位于同一源,并且您依赖Cookie来验证用户,则可以(并且您应该)集成防伪令牌保护,您可以查看此Answer on StackOverflow以了解有关如何实现它的更多详细信息。
但由于您要从外部应用程序调用API,因此只需使用上述方法之一。
查看Microsoft docs上的本文,了解有关CSRF攻击以及如何实现防伪令牌保护的更多详细信息。
另外,请查看RedHat上的这篇文章,以获得关于API security的更多信息。

jdzmm42g

jdzmm42g2#

我以前是一个安全冠军,所以知道什么是安全(但最近没有跟随这个主题)。但在每次会议或培训中,通常有两件事是正确的:
1.安全很难做好
1.安全性很难做好...所以千万不要自己做!!
在您的例子中,问题是API中没有防伪令牌(CSRF保护),它只在MVC中可用,这是有原因的:

*MVC正在使用会话,表单在服务器上呈现,因此令牌在服务器端生成,发送到HTML表单并存储在用户会话中,以进行POST回验证。
*大多数MVC站点使用基于Cookie的身份验证,这会受到CSRF post攻击的影响。
*REST API应该是无状态的,这意味着默认情况下没有会话。响应不是HTML,而是XML/JSON数据。“表单”POST发生在其他系统和安全的方式来暴露防伪令牌。
*大多数RestFul API正在使用oAuth2或一些甚至不受CSRF影响的承载令牌授权!!!

因此,您的问题的答案是另一个问题。您是否在API中使用基于Cookie的授权?

*如果不是,则不应使用防伪令牌,因为它不会影响您的API... * 否则,应切换到Bearer Auth标头并设置。

也请忽略编码的答案,因为他们有很多问题。实现将编译,代码运行肯定,但充满了安全问题(自制安全)。例如,令牌存储在Cookie这是CSRF攻击的基础浏览器自动附加到一个请求的Cookie,GET方法是安全的,甚至不能防止,等等。

自制软件的安全性可能会给予虚假的信心(是的,我“保护”了它),它是否安全?:

yvfmudvl

yvfmudvl3#

我不同意“在构建API时没有必要实现针对CSRF攻击的防伪令牌保护”的答案。
仍然存在这样一种风险,即入侵者可能以某种方式强迫客户端应用程序发送恶意请求。
要在.NET Web API中配置防伪保护(不使用MVC视图),您需要使用包Microsoft.AspNetCore.Antiforgery
请记住,有两个令牌需要验证:Cookie令牌和请求令牌(来自HTTP报头)。

// Field
IAntiforgery _antiforgery;

var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

因此,tokens将包含以下值:

{
    "CookieToken": "CfDJ8JPuS3COPd9AmHCMBz_IFVdVzR8cfeD2or9v3qMLlWgRiN812hKbkh4o8TpYl4AdA3uJ3FeoY3eozx59q_uSnloXl80nLEd6twLzkDdn4AifcsGWcwaAxWSrGTui0vwl7-SHjftCfkbj9pAlDC_DS0Q",
    // Ignore this: built-in mechanism for forms
    "FormFieldName": "__RequestVerificationToken",
    "HeaderName": "X-XSRF-TOKEN",
    "RequestToken": "CfDJ8JPuS3COPd9AmHCMBz_IFVfnP50wBywG2WJmFoYA7nx-VGzBjPRY16-p3BBFRMUGHt4cz-M-VrZ_jX_7vUoIt0OX3xhHNw8swt0CebGa4P41cVej2F_DvvayOvrhbY6s3Z2U1aZWHmAvBT8NlH7ueRE"
}

请注意,CookieTokenRequestToken是不同的。
Cookie令牌是自动处理的。但请求令牌应由我们处理。
1.创建验证中间件:

public class AntiforgeryMiddleware : IMiddleware
{
    private readonly IAntiforgery _antiforgery;

    public AntiforgeryMiddleware(IAntiforgery antiforgery)
    {
        _antiforgery = antiforgery;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var isGetRequest = string.Equals("GET", context.Request.Method, StringComparison.OrdinalIgnoreCase);
        if (!isGetRequest)
        {
            await _antiforgery.ValidateRequestAsync(context);
        }

        await next(context);
    }
}

1.在Web API应用程序中配置DI:

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    // ...

    // Extension method comes from the `Microsoft.AspNetCore.Antiforgery` package
    services.AddAntiforgery(options =>
    {
        options.HeaderName = "X-XSRF-TOKEN";
    });

    services.AddScoped<AntiforgeryMiddleware>();
}

1.配置验证中间件:

// Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseMiddleware<AntiforgeryMiddleware>();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

1.创建XSRF令牌端点:

[Route("api/xsrf-token")]
[ApiController]
public class AntiForgeryController : Controller
{
    private IAntiforgery _antiforgery;

    public AntiForgeryController(IAntiforgery antiforgery)
    {
        _antiforgery = antiforgery;
    }

    [IgnoreAntiforgeryToken]
    public IActionResult Get()
    {
        // Creates and sets the cookie token in a cookie
        // Cookie name will be like ".AspNetCore.Antiforgery.pG4SaGh5yDI"
        var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

        // Take request token (which is different from a cookie token)
        var headerToken = tokens.RequestToken;
        // Set another cookie for a request token
        Response.Cookies.Append("XSRF-TOKEN", headerToken, new CookieOptions
        {
            HttpOnly = false
        });
        return NoContent();
    }
}

1.在客户端上,向URL /api/xsrf-token发出请求。
然后读取一个请求标记cookie XSRF-TOKEN,并将其设置为非GET请求的X-XSRF-TOKEN HTTP头:

X-XSRF-TOKEN: <request-token>

相关问题