我在我的项目Spring MVC和Thymeleaf中使用。让我们说我想要实现非常简单的用法 - 编辑用户的表单。我使用SessionAttributes:
@Controller
@RequestMapping(value="/admin/")
@SessionAttributes(value={"user"})
public class UsersController implements Serializable
请求GET I,我有简单的映射:
@RequestMapping(value={"user/{id}", "{user/{id}/}"}, method=RequestMethod.GET)
public String edit(Model model, @PathVariable(value="id") Long id, RedirectAttributes redirectAttributes){
String username = SecurityUtils.getLoggedUsername(); //for example, Spring Security
User user = userService.getByIdAndUsername(id, username);
model.addAttribute("user", user);
return "admin/user";
}
足够 - 检查会话记录用户是否有权编辑具有指定ID的用户(在此示例中 - 仅限其ID)。带有id的字段不会通过" hidden"填充在他的HTML表单中。字段,它将存储在SessionAttributes中并在调用POST方法后合并。 到现在为止还挺好。但是出现了问题。如果 - 让我们说 - "非常聪明"用户在他的HTML调试器中插入/生成一个POST请求,手动添加名为=" user.id"的隐藏输入。 (或general =" [object name]。[object property]并调用POST方法?SessionAttributes不会被合并,因为在我的HTTP请求属性中存在ID。
@RequestMapping(value="user/{id}", method=RequestMethod.POST)
public String action(@ModelAttribute("user") User user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes){
通过这种方式,任何人都可以编辑某人的ID(假设其他用户的ID已知)并编辑其他用户。如何保护这部分系统? 现在我只有一个解决方案 - 将任何用户视为潜在的窃贼,并以与GET方法相同的方式检查POST方法:
@RequestMapping(value="user/{id}", method=RequestMethod.POST)
public String action(User user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes){
String username = SecurityUtils.getLoggedUsername(); //for example, Spring Security
User otherButTheSameUser = userService.getByIdAndUsername(id, username); //remember to evict this user from hibernate session
if(otherButTheSameUser!=null){
userService.update(user);
}
}
这应该足够安全,但是由于双重SQL检查查询,因此出现了SQL性能问题。这是一个好方法吗?还有另一种方法可以实现吗?也许将@SessionAttributes与sessionAttributes优先级的请求对象合并?如何实现?
答案 0 :(得分:3)
据我所知,您可以使用DataBinder.setAllowedFields()或DataBinder.setDisallowedFields()方法。 Excerpt from javadoc:
In the case of HTTP form POST data for example, malicious clients can
attempt to subvert an application by supplying values for fields or
properties that do not exist on the form. In some cases this could
lead to illegal data being set on command objects or their nested
objects. For this reason, it is highly recommended to specify the
allowedFields property on the DataBinder.
所以,我建议尝试这样的事情:
@InitBinder
protected void initBinder(WebDataBinder binder) {
// please check that it's really working
binder.setDisallowedFields("user.id");
}