【问题标题】:Prevent HTML read-only text fields to be changed防止更改 HTML 只读文本字段
【发布时间】:2020-05-11 05:40:14
【问题描述】:

我正在开发一个 Grails Web 应用程序,它的模块大部分都必须实现一个主从接口。作为一种方法,我想将以下代码供您考虑:

大师班:

import org.codehaus.groovy.grails.web.json.JSONArray

class MyForm {
    String name
    String address
    String detail
    BigDecimal total

    static hasMany = [details: MyFormDetail]

    static constraints = {
        name()
        address()
        detail()
        total()
    }

    static mapping = {
        detail type: 'text'
    }

    def beforeInsert = {
        def detailJSON = new JSONArray(detail)
        detailJSON.each {
            def quantity = it.getAt("quantity").toString().toBigDecimal()
            def description = it.getAt("description").toString()
            def unitaryPrice = it.getAt("unitaryPrice").toString().toBigDecimal()
            def subtotal = it.getAt("subtotal").toString().toBigDecimal()
            def myFormDetail = new MyFormDetail(
                    quantity: quantity,
                    description: description,
                    unitaryPrice: unitaryPrice,
                    subtotal: subtotal
            )
            this.addToDetails(myFormDetail)
        }
    }
}

详细分类:

class MyFormDetail {
    Integer quantity
    String description
    BigDecimal unitaryPrice
    BigDecimal subtotal

    static belongsTo = [myForm: MyForm]

    static constraints = {
        quantity()
        description()
        unitaryPrice()
        subtotal()
    }
}

myFormUtilities.js 帮助文件:

$(document).ready(function() {
    $("#detailTable").jqGrid({
        datatype: "local",
        height: 100,
        colNames: ["QUANTITY","DESCRIPTION","UNIT. PRICE","SUBTOTAL"],
        colModel:[ 
            {name:'quantity',index:'quantity', width:100},
            {name:'description',index:'description', width:400},
            {name:'unitaryPrice',index:'unitaryPrice', width:100},
            {name:'subtotal',index:'subtotal', width:100}],
        caption: "DETAIL"
    });

    createTable();

    $("#addRow").bind("click",addRow);
    $("#removeRow").bind("click",removeRow);

    $("#quantity, #unitaryPrice").bind("keyup",calculateTotal);

    function calculateTotal(){
        let quantity = parseFloat($("#quantity").val());
        let unitaryPrice = parseFloat($("#unitaryPrice").val());
        let subtotal = quantity*unitaryPrice;
        $("#subtotal").val(subtotal);
    }

    function addRow(){
        let row = new Object();
        row.quantity = $("#quantity").val();
        row.description = $("#description").val();
        row.unitaryPrice = $("#unitaryPrice").val();
        row.subtotal = $("#subtotal").val();
        let detailJSON = ($("#detail").val()=="")?"[]":$("#detail").val();
        let mydata = $.parseJSON(detailJSON);
        mydata.push(row);
        $("#detail").val(JSON.stringify(mydata));
        createTable();
    }

    function removeRow(){
        let filaId = parseInt($('#detailTable').jqGrid('getGridParam','selrow')) - 1;
        let mydata = $.parseJSON($("#detail").val());
        let nuevoMydata = new Array();
        for(let i=0;i<mydata.length;i++){
            if(filaId!=i)
                nuevoMydata.push(mydata[i]);
        }
        $("#detail").val(JSON.stringify(nuevoMydata));
        createTable();
    }

    function createTable(){
        let total = 0;
        let aRow = new Object();
        let detailJSON = ($("#detail").val()=="")?"[]":$("#detail").val();
        let mydata = $.parseJSON(detailJSON);
        $("#detailTable").jqGrid("clearGridData", true);
        for(let i=0;i<mydata.length;i++){
            aRow = mydata[i];
            total += parseFloat(aRow.subtotal);
            $("#detailTable").jqGrid('addRowData',i+1,aRow);
        }
        $("#total").val(total);
    }
});

这是显示的表单(我知道这是一个自动生成的视图,但请把它看作一个非常基本的 GUI 模型):

所以,这些是问题:

  • SubtotalTotal 字段都是已设置的计算字段 read-only 防止用户修改他们的内容,但我发现 使用浏览器元素检查器它们的内容和属性 (如只读)可以修改。

  • detail 也是如此。如果其内容被更改,服务器端 保存实例时将产生错误,因为beforeInsert 块需要有效 用于创建 detail 实例的 JSON 字符串。此字段还用于生成详细信息 JqGrid。该字段将是 隐藏。

本示例中的所有内容都按预期工作,但可能由好奇的用户引起。

  • 有没有办法防止这些字段文本被更改,即使使用 检查员?
  • 还有其他地方可以保护这些数据免受更改吗?
  • 我正在使用这个detail 字段来保存一个JSON 字符串,这是我实现主从模式的解决方案。有没有别的 改进此实现的方法,避免定义一个 这个字符串的字段?

【问题讨论】:

  • 因此,如果您不希望用户编辑值,则不要接受对该值服务器端的更改。因此,例如,价格...不要相信来自客户端的价格值。仅信任 Price 服务器端的值(来自您的数据库)。还是我误解了你的问题?

标签: javascript html grails jqgrid master-detail


【解决方案1】:

如果您有不想参与批量属性数据绑定的属性,则应使用bindable: false 对其进行配置。

你有这个:

class MyFormDetail {
    Integer quantity
    String description
    BigDecimal unitaryPrice
    BigDecimal subtotal

    static belongsTo = [myForm: MyForm]

    static constraints = {
        quantity()
        description()
        unitaryPrice()
        subtotal()
    }
}

你可以把它改成这样:

class MyFormDetail {
    Integer quantity
    String description
    BigDecimal unitaryPrice
    BigDecimal subtotal

    static belongsTo = [myForm: MyForm]

    static constraints = {
        quantity()
        description()
        unitaryPrice bindable: false
        subtotal bindable: false
    }
}

如果你有这样的事情:

MyFormDetail mfd = new MyFormDetail()
// The body of the request will be read and
// bound to mfd but subtotal and unitaryPrice
// will NOT be updated...
mfd.properties = request

如果你这样做,你仍然可以直接为这些属性赋值:

mfd.subtotal = // ... some value here

另一种选择是将表单提交给接受命令对象的控制器操作。那个 CO 可能看起来像这样......

class FormCommand {
    Integer quantity
    String description
}

如果您有如下所示的操作:

class SomeController {
    def someAction(FormCommand co) {
        // it won't matter if subtotal
        // and unitaryPrice are in the
        // request, the co only has the
        // the properties you want so now
        // you can use those to update the
        // corresponding persistent entity
        // in a safe way
    }
}

【讨论】:

    【解决方案2】:

    抱歉,保护从浏览器发送的数据没有简单的方法。您的服务器应将任何用户提交的输入视为脏输入。

    在 POST 或 GET 中发送的数据始终可以在客户端进行更改,甚至可以批量创建(使用 CURL 或 Postman 之类的东西)。因此,您应该始终在服务器端验证用户输入并在那里计算您的总数。

    【讨论】:

      【解决方案3】:

      如果您的用户可以访问检查器/Web 控制台,那么他们就可以访问您所做的所有客户端数据(他们只受他们对如何使用浏览器开发工具的了解程度的限制)。他们可以更改任何元素的文本或输入的值。因此,唯一可以 100% 安全存储这些数据的地方是服务器端。

      您可以尝试隐藏每个输入(例如使用 CSS)并将其替换为带有 &lt;span&gt; 元素(或其他一些非表单元素)的可见 HTML。然后确保每当&lt;input&gt; 值发生更改时,都会更新相应范围的文本。比如:

      $("#subtotalSpan").html( $("#subtotal").val() );
      

      在 calculateTotal 函数中添加。如果您希望他们甚至无法编辑跨度的 HTML,您可以更进一步,将值绘制到 &lt;canvas&gt; 而不是 &lt;span&gt;。他们将无法更改绘制到画布元素中的文本。

      【讨论】:

        猜你喜欢
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多