简体   繁体   English

为匿名用户使用CSRF保护是否有意义?

[英]Does it make sense to use CSRF protection for anonymous users?

Should CSRF protection be used for anonymous users, or does that defeat its purpose? CSRF保护是否应该用于匿名用户,还是会破坏其目的?

I have a URL that can be accessed anonymously. 我有一个可以匿名访问的URL。 When the URL is accessed with the appropriate information, some values are updated in my database. 使用适当的信息访问URL时,会在我的数据库中更新某些值。 For example, a client can place some code on their order confirmation page that will make a POST request to http://example.com/save-request with the following data sent: 例如,客户可以在其订单确认页面上放置一些代码,这些代码确认页面会向http://example.com/save-request发送POST请求,并发送以下数据:

{orderId: 1234, referralCode: 'ABCDEF'}

When I receive this request, I update the given order in my database with the referral code: 当我收到此请求时,我使用引用代码更新数据库中的给定订单:

$order = Order::find(Input::get('orderId'));
$order->referral_code = Input::get('referralCode');
$order->save();

I am trying to protect this URL from abuse so that a user can't send requests for random Order IDs and try to get their referral code associated to them. 我正在尝试保护此URL免遭滥用,以便用户无法发送随机订单ID的请求,并尝试获取与其关联的引荐代码。

CRSF protection comes to mind, but that would mean I need to first fetch the token, which would require another public URL. 我想到了CRSF保护,但这意味着我需要首先获取令牌,这需要另一个公共URL。 It seems like that would make it slightly harder for abuse, but still possible since the abuser can simply fetch a token, and then make requests as normal. 似乎这会使滥用稍微困难,但仍然可能,因为滥用者可以简单地获取令牌,然后正常发出请求。

Are there any strategies to protect against this sort of abuse? 有没有什么策略可以防止这种滥用?

CSRF is meant to protect authenticated sessions. CSRF旨在保护经过身份验证的会话。 The basic idea is: the server provides a CSRF token to the client for all authenticated sessions. 基本思想是:服务器为客户端提供所有经过身份验证的会话的CSRF令牌。 The client should pass the same CSRF token to the server with each subsequent request. 客户端应在每次后续请求时将相同的CSRF令牌传递给服务器。 So if a request came without the token, the server should ignore / log it. 因此,如果请求没有令牌,服务器应该忽略/记录它。 Your CSRF token should ideally only be passed to the client upon authentication . 理想情况下,您的CSRF令牌只能在身份验证时传递给客户端。 If there's a separate URL to get the CRSF token, it becomes pointless. 如果有一个单独的URL来获取CRSF令牌,它就变得毫无意义。

In your case, since the users are always anonymous at "order confirmation", CSRF protection would not be too applicable. 在您的情况下,由于用户在“订单确认”中始终是匿名的,因此CSRF保护不会太适用。 I think the best strategy would be to model the data and your API such that each "order confirmation" is one atomic request with an optional "referralCode". 我认为最好的策略是对数据和API建模,使每个“订单确认”是一个带有可选“referralCode”的原子请求。 Your API function/endpoint, possibly /confirm-order , can then take referralCode and save it into the Order object, along with any other confirmation processing logic. 然后,您的API函数/端点(可能是/confirm-order )可以使用referralCode并将其与任何其他确认处理逻辑一起保存到Order对象中。 The API function/endpoint to edit order, maybe /edit-order , should require authentication. 用于编辑订单的API函数/端点,可能/edit-order ,应该要求验证。 Then, the standard CSRF protection applies. 然后,适用标准CSRF保护。

However, if your intention is to allow anonymous users to change their order details including referralCode , you can mitigate abuse by tracking changes, and allowing only a maximum number of changes. 但是,如果您打算允许匿名用户更改其订单详细信息(包括referralCode ,则可以通过跟踪更改来缓解滥用行为,并且仅允许最大数量的更改。 You may also add in some time restriction if it helps. 如果有帮助,您也可以添加一些时间限制。

I agree that a CSRF token is not useful for unauthenticated requests but it also makes no harm and adds no extra work (in case of Laravel), so in most cases there are no real reasons to omit it here and there. 我同意CSRF令牌对于未经身份验证的请求没有用,但它也没有任何损害,也没有额外的工作(如果是Laravel),所以在大多数情况下没有真正的理由在这里和那里省略它。

What regards to solution of your problem, try replacing an id of an order with something like a generated random order_number which is much more difficult to guess than a simple id. 关于你的问题的解决方案,尝试用生成的随机order_number替换订单的id ,这比简单的id要难得多。

Another solution is something like this: 另一种解决方案是这样的:

$order = Order::where('id', '=', Input::get('orderId'))
    ->where('created_at', '=', Input::get('createdAt'))->first();

if ($order) {
    $order->referral_code = Input::get('referralCode');
    $order->save();
}

In this case a user has to guess an id and also guess when a particular order has been created. 在这种情况下,用户必须猜测id并且还猜测何时创建了特定订单。

And you can also mix both solutions ( order_number and created_at ). 您还可以混合使用两种解决方案( order_numbercreated_at )。

It's not a perfect 100% solution but drastically decreases probability of fraud. 这不是一个完美的100%解决方案,但大大降低了欺诈的可能性。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM