什么是“正确的”?或“安全”用Spring MVC 3 + Hibernate更新持久对象的方法? [英] What is the "correct" or "safe" way to update a persisted object with Spring MVC 3 + Hibernate?

查看:124
本文介绍了什么是“正确的”?或“安全”用Spring MVC 3 + Hibernate更新持久对象的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个非常简单的对象:

  class User {
private Integer id;
私人字符串名称;

public User(){}
$ b $ public Integer getId(){return id; }
public String getName(){return name; }

public void setName(String name){this.name = name; }
}

和一个非常简单的控制器动作:

  @RequestMapping(value =/ edit / {id} / **,method = RequestMethod.POST)
public String editFromForm(@PathVariable id)整数id,@Valid用户用户,BindingResult bindingResult,模型​​模型){
//如果我们有错误,不要保存
if(bindingResult.hasErrors()){
//把他们在模型中做的事情发回给
model.addAttribute(user);

返回users / edit;
} else {
userDAO.save(user);
}

//向他们显示成功的更新页面
返回redirect:/ users /+ user.getId()+/+ user.getName() ;
}

和一个非常简单的形式:

 < sf:form method =POSTmodelAttribute =user> 
< label for =user_name>名称:< / label>
< sf:input path =nameid =user_name/>
< input type =submitvalue =save/>< sf:errors path =namecssClass =error/>
< / sf:form>

我应该如何更新数据库中的实体?目前(因为 saveOrUpdate()是DAO的 save()方法后的实际hibernate调用,所以一个新对象被保存而不是更新现有的,因为 id 字段没有在表单提交创建的对象上设置。



我遇到了一些可能的解决方案,但我不确定在保持事物清洁和安全方面哪个最好(以便恶意用户不能仅仅编辑他们希望的任何对象ID)。


  1. 将URL参数中的id插入到来自模型联编程序的对象中
  2. 隐藏 b
    $ b $ p
    $ b $ p
  3. 在表单中的c $ c> id 字段中,并让模型联编程序附加id在这些情况下,没有检查以确保对象仍然是相同的,例如某种校验和。其他人如何处理这个问题?是否有任何明确的例子可以解决这个问题?



    另一个问题是我宁愿不需要 setId()方法,因为Hibernate正在管理所有的id。从我已经能够确定的情况来看,Spring MVC模型绑定器只能绑定一个字段,如果它具有期望的getter和setter。有没有其他的方式来应用新的状态,比如通过URL的 id 参数从数据库获取当前用户,然后将新状态应用到它,但是没有显式编码所有的字段副本?



    我相信有一个相当简单,直接的方法来处理这个问题,但我的热瘾大脑似乎不是能够想出一个合适的解决方案。

    我对Spring + Hibernate相当陌生,所以原谅我,如果这是那些平凡的,高度覆盖的主题之一,但我一直未能找到涵盖我非常简单的情况的任何明确的例子。如果在其他地方被充分说明,请指出我的正确方向。

    解决方案


    一些可能的解决方案已经发布给我了,但我不确定哪些方法最有利于保持内容的清洁和安全(以便恶意用户不能仅仅编辑任何对象标识就可以) 。

    您提到的两种方法都不会处理尝试编辑用户未被授权的对象的用户。在一天结束时,提交表单的用户需要告诉你他们提交数据的对象 - 不管它是在URL参数中还是在隐藏的表单参数中。我会说你选择哪一个是风格和个人喜好的问题,真的。

    但是无论你选择什么,你需要做的是验证当前登录的用户有权在处理表单提交时更改对象。这意味着您需要检查该用户是否有权编辑当前的对象ID,使用包含允许为此执行此操作的任何逻辑来为您的应用程序进行编辑。


    Given a very simple object:

    class User {
        private Integer id;
        private String name;
    
        public User() {}
    
        public Integer getId() { return id; }
        public String getName() { return name; }
    
        public void setName(String name) { this.name = name; }
    }
    

    and a very simple controller action:

    @RequestMapping(value="/edit/{id}/**", method=RequestMethod.POST)
    public String editFromForm(@PathVariable("id") Integer id, @Valid User user, BindingResult bindingResult, Model model) {
        // If we have errors, don't save
        if(bindingResult.hasErrors()) {
            // Put what they did in the model and send it back
            model.addAttribute(user);
    
            return "users/edit";
        } else {
            userDAO.save(user);
        }
    
        // Show them the updated page on success
        return "redirect:/users/" + user.getId() + "/" + user.getName();
    }
    

    and a very simple form:

    <sf:form method="POST" modelAttribute="user">
        <label for="user_name">Name:</label>
        <sf:input path="name" id="user_name" />
        <input type="submit" value="save" /><sf:errors path="name" cssClass="error" />              
    </sf:form>
    

    How should I be updating the entity in the database? Currently (since saveOrUpdate() is the actual hibernate call behind my DAO's save() method, a new object is persisted instead of updating the existing one because the id field is not being set on the object created from the form submission.

    A couple of possible solutions have come to me, but I am not sure which is best in terms of keeping things clean and also secure (so that a malicious user cannot just fire in edits to whatever object Id's they wish).

    1. Insert the id from the URL parameter into the object coming from the model binder
    2. Have a hidden id field in the form and let the model binder attach the id

    In both of those cases, there is no check in place to make sure that the object is still the same one, such as a checksum of some sort. How do others deal with this? Are there any clear example that walk through this issue?

    Another issue that comes up is that I'd rather not need a setId() method since Hibernate is managing all of the id's. From what I have been able to determine, the Spring MVC model binder can only bind a field if it has the expected getter and setter. Is there some other way to apply the new state, such as getting the current User from the db by the URL's id parameter and then applying the new state to it, but without having to explicitly code all of the field copies?

    I am sure there is a fairly simple, straightforward way to handle this, but my heat-addled brain does not seem to be able to come up with a suitable solution.

    I'm fairly new to Spring + Hibernate so forgive me if this is one of those mundane, highly covered topics, but I have not been able to find any clear example that covers my very simple situation. If this has been covered sufficiently elsewhere, please point me in the right direction.

    解决方案

    A couple of possible solutions have come to me, but I am not sure which is best in terms of keeping things clean and also secure (so that a malicious user cannot just fire in edits to whatever object Id's they wish).

    Neither of the two approaches you mention will really handle a user who is attempting to edit objects that the user is not authorized to. At the end of the day, the user submitting the form needs to tell you which object they are submitting data for - whether it is in the URL parameter or in a hidden form parameter. I would say which of the two you choose is a matter of style and personal preference, really.

    But what you need to be doing regardless of choice is to verify that the currently-logged-in user is authorized to change the object when processing the form submission. This would mean you need to check that this user is entitled to edit the current object ID, using whatever logic comprises "is allowed to do this" for your application.

    这篇关于什么是“正确的”?或“安全”用Spring MVC 3 + Hibernate更新持久对象的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆