𝗥𝗮𝗰𝗶𝗻𝗴 𝗮 𝗡𝗲𝘅𝘁.𝗷𝘀 𝗔𝗣𝗜 𝗥𝗼𝘂𝘁𝗲
ਇੱਕ ਵਾਰ ਵਰਤੋਂ ਵਾਲਾ ਕੂਪਨ ਸਿਰਫ਼ ਇੱਕ ਵਾਰ ਹੀ ਕੰਮ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ।
ਪਰ ਇਸ ਸਥਿਤੀ ਵਿੱਚ, ਤੀਹ ਲੋਕ ਇਸਨੂੰ ਬਿਲਕੁਲ ਇੱਕੋ ਸਮੇਂ ਵਰਤ ਸਕਦੇ ਹਨ।
ਇਹ Time-of-Check Time-of-Use (TOCTOU) race condition ਕਾਰਨ ਹੁੰਦਾ ਹੈ।
ਗਲਤੀ ਦੋ ਪੜਾਵਾਂ ਵਿੱਚ ਹੁੰਦੀ ਹੈ:
- ਪੜਾਅ 1: ਸਰਵਰ ਵਰਤੋਂ ਦੀ ਗਿਣਤੀ (used count) ਦੀ ਜਾਂਚ ਕਰਨ ਲਈ ਡਾਟਾਬੇਸ ਨੂੰ ਪੜ੍ਹਦਾ ਹੈ।
- ਪੜਾਅ 2: ਸਰਵਰ ਉਸ ਗਿਣਤੀ ਨੂੰ ਵਧਾਉਣ ਲਈ ਦੂਜੀ ਕਮਾਂਡ ਭੇਜਦਾ ਹੈ।
ਜੇਕਰ ਤੁਸੀਂ ਇੱਕੋ ਵਾਰ ਕਈ ਰਿਕਵੈਸਟਾਂ ਭੇਜਦੇ ਹੋ, ਤਾਂ ਸਰਵਰ ਇਹਨਾਂ ਦੋਵਾਂ ਪੜਾਵਾਂ ਦੇ ਵਿਚਕਾਰ ਹੀ ਉਹਨਾਂ ਸਾਰੀਆਂ ਨੂੰ ਸੰਭਾਲ ਲੈਂਦਾ ਹੈ।
ਕਈ ਰਿਕਵੈਸਟਾਂ ਗਿਣਤੀ ਨੂੰ ਉਦੋਂ ਪੜ੍ਹਦੀਆਂ ਹਨ ਜਦੋਂ ਇਹ ਅਜੇ ਵੀ ਜ਼ੀਰੋ ਹੁੰਦੀ ਹੈ। ਉਹ ਸਾਰੀਆਂ ਜਾਂਚ (check) ਵਿੱਚੋਂ ਲੰਘ ਜਾਂਦੀਆਂ ਹਨ। ਉਹ ਸਾਰੀਆਂ ਡਿਸਕਾਊਂਟ ਲਾਗੂ ਕਰਦੀਆਂ ਹਨ। ਉਹ ਸਾਰੀਆਂ ਕਾਊਂਟਰ ਨੂੰ ਵਧਾ ਦਿੰਦੀਆਂ ਹਨ।
ਨਤੀਜਾ? ਇੱਕ ਵਿਅਕਤੀ ਲਈ ਬਣਾਇਆ ਗਿਆ ਕੂਪਨ ਤੀਹ ਵਾਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।
ਕੋਡ ਰਿਵਿਊ ਦੌਰਾਨ ਇਸ ਨੂੰ ਨਜ਼ਰਅੰਦਾਜ਼ ਕਰਨਾ ਆਸਾਨ ਹੈ। ਜਦੋਂ ਤੁਸੀਂ ਇਸਨੂੰ ਲਾਈਨ ਦਰ ਲਾਈਨ ਪੜ੍ਹਦੇ ਹੋ, ਤਾਂ ਲੌਜਿਕ ਬਿਲਕੁਲ ਸਹੀ ਲੱਗਦਾ ਹੈ। ਇਹ ਖਾਮੀ ਉਦੋਂ ਹੀ ਸਾਹਮਣੇ ਆਉਂਦੀ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਰਫ਼ਤਾਰ ਅਤੇ concurrency ਬਾਰੇ ਵਿਚਾਰ ਕਰਦੇ ਹੋ।
ਇਸ ਨੂੰ ਕਿਵੇਂ ਠੀਕ ਕਰੀਏ:
ਵੱਖ-ਵੱਖ read ਅਤੇ write ਕਮਾਂਡਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨਾ ਬੰਦ ਕਰੋ। ਇਸ ਦੀ ਬਜਾਏ, ਇੱਕ ਸਿੰਗਲ atomic operation ਦੀ ਵਰਤੋਂ ਕਰੋ।
Prisma ਵਿੱਚ, ਤੁਸੀਂ WHERE clause ਵਿੱਚ ਇੱਕ ਸ਼ਰਤ (condition) ਦੇ ਨਾਲ updateMany ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹੋ:
• ਡਾਟਾਬੇਸ ਸ਼ਰਤ ਦੀ ਜਾਂਚ ਕਰਦਾ ਹੈ ਅਤੇ ਇੱਕੋ ਵਾਰ ਵਿੱਚ ਅੱਪਡੇਟ ਕਰ ਦਿੰਦਾ ਹੈ। • ਜੇਕਰ ਗਿਣਤੀ ਪਹਿਲਾਂ ਹੀ ਸੀਮਾ (limit) 'ਤੇ ਹੈ, ਤਾਂ ਅੱਪਡੇਟ ਤੁਰੰਤ ਫੇਲ੍ਹ ਹੋ ਜਾਂਦਾ ਹੈ। • ਜਾਂਚ ਅਤੇ ਲਿਖਣ (write) ਦੇ ਵਿਚਕਾਰ ਕੋਈ ਹੋਰ ਰਿਕਵੈਸਟ ਨਹੀਂ ਆ ਸਕਦੀ।
ਇੱਕ ਹੋਰ ਵਿਕਲਪ ਡਾਟਾਬੇਸ transaction ਦੀ ਵਰਤੋਂ ਕਰਨਾ ਹੈ। ਇਹ ਡਾਟਾ ਨੂੰ ਲੌਕ ਕਰ ਦਿੰਦਾ ਹੈ ਤਾਂ ਜੋ ਤੁਹਾਡੇ ਮੁਕੰਮਲ ਹੋਣ ਤੱਕ ਕੋਈ ਹੋਰ ਰਿਕਵੈਸਟ ਇਸਨੂੰ ਛੂਹ ਨਾ ਸਕੇ।
SQLite ਲਈ, ਸਿੰਗਲ update ਕਮਾਂਡ ਸਭ ਤੋਂ ਭਰੋਸੇਮੰਦ ਤਰੀਕਾ ਹੈ।
ਹਮੇਸ਼ਾ ਆਪਣੇ ਆਪ ਨੂੰ ਪੁੱਛੋ: ਕੀ ਹੁੰਦਾ ਹੈ ਜੇਕਰ ਦੋ ਰਿਕਵੈਸਟਾਂ ਇੱਕੋ ਮਿਲੀਸੈਕਿੰਡ ਵਿੱਚ ਇਸ ਲੌਜਿਕ 'ਤੇ ਪਹੁੰਚਦੀਆਂ ਹਨ?
Source: https://dev.to/oopssec-store/racing-a-nextjs-api-route-coupon-abuse-with-prisma-and-sqlite-3gma