@InitBinder防止从JSP更新对象(@InitBinder prevents updatin

2019-10-29 15:28发布

我明白@InitBinder用于安全方面的原因,但它引起了我的各种问题。

我有一个UserController的一个更新方法如下。

    @Secured(value={"ROLE_ADMIN"})
    @Transactional
    @RequestMapping(value="/user/{id}", method=RequestMethod.PUT)
    public String userUpdate(User user, BindingResult userBinding, Model model, @PathVariable long id) {

    if (userBinding.hasErrors()) {
        return (String.format("user/{%s}/edit", String.valueOf(user.getId())));
    }

    try {
        userService.updateUser(user);
    }
    catch (Exception e) {
        logger.error("Unable to update user", e);
    }

    return "redirect:/user";
}

而且我有这个是我的UserController的为好。

@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
    dataBinder.setDisallowedFields("id");
}

我的JSP来处理创建和更新如下。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

<div class="container">
    <div class="row">
        <div class="col-xs-12">
            <spring:bind path="user.*">
                <c:if test="${status.errors.errorCount > 0}">
                    <div class="alert alert-danger">
                        <p>Error: unable to save, please check the errors below</p>
                    </div>
                </c:if>
            </spring:bind>
        </div>
    </div>
    <div class="row">
        <div class="col-xs-12 col-sm-8 col-md-6">
            <h3>User - Add</h3>
            <br>

            <c:choose>
                <c:when test="${user.id > 0}">
                    <c:set var="formMethod" value="PUT" />
                    <c:url var="formAction" value="/user/${user.id}" />
                </c:when>
                <c:otherwise>
                    <c:set var="formMethod" value="POST" />
                    <c:url var="formAction" value="/user" />
                </c:otherwise>
            </c:choose>

            <sf:form method="${formMethod}" action="${formAction}" commandName="user">
                <spring:bind path="user.id">
                    <sf:hidden path="${status.expression}" id="user-id" />
                </spring:bind>
                <spring:bind path="user.firstName">
                    <div class="form-group">
                        <label for="first-name">First Name</label>
                        <sf:input path="${status.expression}" id="first-name" class="form-control" placeholder="First Name" />
                        <sf:errors path="${status.expression}" cssClass="error-message"></sf:errors>
                    </div>
                </spring:bind>
                <spring:bind path="user.lastName">
                    <div class="form-group">
                        <label for="last-name">Last Name</label>
                        <sf:input path="${status.expression}" id="last-name" class="form-control" placeholder="Last Name" />
                        <sf:errors path="${status.expression}" cssClass="error-message"></sf:errors>
                    </div>
                </spring:bind>
                <spring:bind path="user.email">
                    <div class="form-group">
                        <label for="email">Email</label>
                        <sf:input path="${status.expression}" id="email" class="form-control" placeholder="Email" />
                        <sf:errors path="${status.expression}" cssClass="error-message"></sf:errors>
                    </div>
                </spring:bind>
                <spring:bind path="user.username">
                    <div class="form-group">
                        <label for="user-name">Username</label>
                        <sf:input path="${status.expression}" id="user-name" class="form-control" placeholder="Username" />
                        <sf:errors path="${status.expression}" cssClass="error-message"></sf:errors>
                    </div>
                </spring:bind>
                <spring:bind path="user.password">
                    <div class="form-group">
                        <label for="password">Password</label>
                        <sf:password path="${status.expression}" id="password" class="form-control" placeholder="" />
                        <sf:errors path="${status.expression}" cssClass="error-message"></sf:errors>
                    </div>
                </spring:bind>
                <div class="form-group">
                    <label for="confirm-password">Confirm Password</label>
                    <input type="password" name="password-confirm" id="confirm-password" class="form-control" placeholder="" />
                </div>
                <spring:bind path="user.roleId">
                    <div class="form-group">
                        <label for="role">Role</label>
                        <sf:select path="${status.expression}" id="role" class="form-control" >
                            <sf:options items="${roles}" itemLabel="name" itemValue="id"/>
                        </sf:select>
                        <sf:errors path="${status.expression}" cssClass="error-message"></sf:errors>
                    </div>
                </spring:bind>
                <button type="submit" class="btn btn-default">Save</button>
                <button type="button" class="btn btn-default">Cancel</button>
            </sf:form>
        </div>
    </div>
</div>

到userService.update(用户)呼叫呼叫JPA合并方法。 它失败,因为它试图插入包含一个唯一约束,这是已经在数据库中的新纪录。 不用通过代码,互联网和堆栈跟踪挖了几个小时之后说,我意识到未来从JSP后面的ID为null。 有一次,我注释掉@InitBinder方法一切都开始正常工作。 这使我想起我的真正的问题,我需要为@InitBinder原因secuirty,如果是的话我怎么解决这个问题我刚才所描述的?

文章来源: @InitBinder prevents updating objects from JSP