将 javascript 计算值传递给数据库是不好的做法吗?
Is it bad practice to pass javascript calculated values to database?
假设我有一个包含 3 个输入字段的表单:
- 总金额
- 增值税率
- 净额
用户可以填写毛额和增值税率字段。 净额字段设置为readonly
。
现在我想通过让 javascript 计算 净额 并填写必填字段并将此值传递给数据库来节省时间并提高性能。
我唯一要检查的是 净额 字段是否为空,例如Symfony NotBlank constraint.
采用 javascript 计算值是不好还是不好的做法?
这里存在三个危险:
- 恶意代码注入
这是通过将用户直接输入的内容显示回屏幕或用户篡改数据的另一个屏幕来实现的。例如,要求用户输入他们的姓名和类型 <script>alert('You got hacked!');</script>
而不是他们的姓名。每个查看其个人资料的用户都会看到此代码,如果您不检查,它可能会在每个查看的人的机器上执行它。
如果您在系统中有一个页面显示用户输入的数据而不先检查它,就会发生这种情况,在您的情况下可能是一个显示数据库当前值的页面。
您可以通过清理用户输入的内容或在离开数据库时检查它来避免这种情况。
但是对于您的情况,如果您将值作为数字而不是字符串存储在数据库中,那么您就不会有问题。
- 操纵 javascript
中的值
虽然你有一个更大的问题,那就是你应该在服务器端执行计算。用户可以操纵净金额的值并将他们想要的任何内容发送到数据库。
例如,如果用户从在线商店购买商品,并且他们将 5 件商品添加到他们的购物车中,每件价格为 £1.00,那么如果您计算总计 javascript(£5.00)并提交并存储它,用户可以对其进行编辑并将总计更改为 £0 并免费获得这些物品。
为了安全起见,您当然应该计算服务器上的成本,并使用您个人从数据库中检索的值 - 不要 re-use 后端用户发送的任何数据,因为它们也可以也将单个项目成本编辑为 0 英镑。
- Javascript 数字准确度
作为奖励,您还应注意,当您将数字相加和相乘时,您的前端和后端可能会以不同的方式计算值。考虑这段代码:
var total = 0.3 - 0.2;
如果您期望总数为 0.1,那您就错了 - 答案类似于 0.99999999998。
Javascript 不能非常准确地处理浮点数。
永远不要相信用户。在服务器端尽你所能,即使你已经在客户端完成了 - 特别是不是像这样的简单计算不会在服务器端为你节省几乎任何时间。
编辑:除非像 Sharky 所说的那样,您实际上并不关心其他两个值,并且只是出于礼貌向用户提供计算。在这种情况下,净值是真正的输入字段——即使它在技术上是只读的。验证它并照原样存储它,甚至不必费心传输其他两个。
假设我有一个包含 3 个输入字段的表单:
- 总金额
- 增值税率
- 净额
用户可以填写毛额和增值税率字段。 净额字段设置为readonly
。
现在我想通过让 javascript 计算 净额 并填写必填字段并将此值传递给数据库来节省时间并提高性能。
我唯一要检查的是 净额 字段是否为空,例如Symfony NotBlank constraint.
采用 javascript 计算值是不好还是不好的做法?
这里存在三个危险:
- 恶意代码注入
这是通过将用户直接输入的内容显示回屏幕或用户篡改数据的另一个屏幕来实现的。例如,要求用户输入他们的姓名和类型 <script>alert('You got hacked!');</script>
而不是他们的姓名。每个查看其个人资料的用户都会看到此代码,如果您不检查,它可能会在每个查看的人的机器上执行它。
如果您在系统中有一个页面显示用户输入的数据而不先检查它,就会发生这种情况,在您的情况下可能是一个显示数据库当前值的页面。
您可以通过清理用户输入的内容或在离开数据库时检查它来避免这种情况。
但是对于您的情况,如果您将值作为数字而不是字符串存储在数据库中,那么您就不会有问题。
- 操纵 javascript 中的值
虽然你有一个更大的问题,那就是你应该在服务器端执行计算。用户可以操纵净金额的值并将他们想要的任何内容发送到数据库。
例如,如果用户从在线商店购买商品,并且他们将 5 件商品添加到他们的购物车中,每件价格为 £1.00,那么如果您计算总计 javascript(£5.00)并提交并存储它,用户可以对其进行编辑并将总计更改为 £0 并免费获得这些物品。
为了安全起见,您当然应该计算服务器上的成本,并使用您个人从数据库中检索的值 - 不要 re-use 后端用户发送的任何数据,因为它们也可以也将单个项目成本编辑为 0 英镑。
- Javascript 数字准确度
作为奖励,您还应注意,当您将数字相加和相乘时,您的前端和后端可能会以不同的方式计算值。考虑这段代码:
var total = 0.3 - 0.2;
如果您期望总数为 0.1,那您就错了 - 答案类似于 0.99999999998。
Javascript 不能非常准确地处理浮点数。
永远不要相信用户。在服务器端尽你所能,即使你已经在客户端完成了 - 特别是不是像这样的简单计算不会在服务器端为你节省几乎任何时间。
编辑:除非像 Sharky 所说的那样,您实际上并不关心其他两个值,并且只是出于礼貌向用户提供计算。在这种情况下,净值是真正的输入字段——即使它在技术上是只读的。验证它并照原样存储它,甚至不必费心传输其他两个。