当程序将非将HTTP请求参数直接绑定给对象时,应该要控制绑定到对象的属性,防止暴露所有属性。
    在Spring MVC中,可以配置绑定器使用setAllowedFields和setDisallowedFields方法控制属性绑定过程以控制应绑定的属性。
    例1:在以下代码片段中,在 Spring MVC(3.0版本至最新)通过setDisallowedFields方法禁止绑定敏感属性。

    1. @InitBinder
    2. public void initBinder(WebDataBinder binder) {
    3. binder.setDisallowedFields(new String[]{"admin"});
    4. }
    5. @RequestMapping("/login" )
    6. public String login(User user) {
    7. ...
    8. }

    例2:在 Spring MVC(2.X版本)通过setDisallowedFields方法禁止绑定敏感属性。

    1. @Override
    2. protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    3. binder.setDisallowedFields(new String[]{"admin"});
    4. }

    而在使用 @RequestBody注释参数的 Spring MVC应用程序中,绑定过程由HttpMessageConverter进行处理,这些实例使用Jackson和JAXB等库将 HTTP请求参数转换为Java对象。这些库提供了注释来控制应允许或禁止的字段。例如对于Jackson,可以使用@JsonIgnore注释禁止将某个字段绑定到请求。

    例3:在以下代码片段中,Jackson禁止绑定敏感属性。

    1. @RequestMapping(value="/add/user", method=RequestMethod.POST, consumes="text/html")
    2. public void addEmployee(@RequestBody User user){
    3. ...
    4. }
    5. public class User {
    6. private String username;
    7. private String address;
    8. @JsonIgnore
    9. private boolean admin;
    10. private int age;
    11. ...
    12. }

    同理,Jackson还可以使用@JsonIgnoreProperties、@JsonIgnoreType和 @JsonInclude等注解告诉框架忽略这些属性,使用JAXB使用@XmlAccessorType、@XmlAttribute、@XmlElement和 @XmlTransient等注解告诉框架忽略这些属性,然后使用@XmlAttribute和@XmlElement等注解选择应绑定的字段。

    例4:在以下代码片段中,Jackson使用@XmlAttribute选择要绑定的字段。

    1. @XmlRootElement
    2. @XmlAccessorType(XmlAccessType.NONE)
    3. public class User {
    4. private String username;
    5. private String address;
    6. @JsonIgnore
    7. private boolean admin;
    8. private int age;
    9. @XmlAttribute
    10. public String getUsername() {
    11. return username;
    12. }
    13. public void setUsername(String username) {
    14. this.username = username;
    15. }
    16. @XmlAttribute
    17. public String getAddress() {
    18. return address;
    19. }
    20. public void setAddress(String address) {
    21. this.address = address;
    22. }
    23. private boolean isAdmin() {
    24. return admin;
    25. }
    26. private void setAdmin(boolean admin) {
    27. this.admin = admin;
    28. }
    29. ...
    30. }

    在Struts 1和 2 中,如果某个属性不应绑定到请求,则应将其 setter方法设置为私有即可。

    例5:在以下代码片段中,在Struts可以将某个属性的setter方法设置为私有从而禁止绑定敏感属性。

    1. private boolean admin;
    2. private void setAdmin(boolean admin) {
    3. this.admin = admin;
    4. }

    还有另一种方法是使用将 HTTP请求参数绑定到仅含有Web表单或API中定义的属性DTO对象中,再将其映射到User中,防止敏感字段暴露。