This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org

Difference between revisions of "Bean Validation Cheat Sheet"

From OWASP
Jump to: navigation, search
m (Point to the official site)
 
(11 intermediate revisions by 5 users not shown)
Line 2: Line 2:
 
<div style="width:100%;height:160px;border:0,margin:0;overflow: hidden;">[[File:Cheatsheets-header.jpg|link=]]</div>
 
<div style="width:100%;height:160px;border:0,margin:0;overflow: hidden;">[[File:Cheatsheets-header.jpg|link=]]</div>
  
Last revision (mm/dd/yy): '''{{REVISIONMONTH}}/{{REVISIONDAY}}/{{REVISIONYEAR}}'''
+
The Cheat Sheet Series project has been moved to [https://github.com/OWASP/CheatSheetSeries GitHub]!
= Bean Validation Introduction =
 
__TOC__{{TOC hidden}}
 
  
This article is focused on providing clear, simple, actionable guidance for providing Java Bean Validation security functionality in your applications.
+
Please visit [https://cheatsheetseries.owasp.org/cheatsheets/Bean_Validation_Cheat_Sheet.html Bean Validation Cheat Sheet] to see the latest version of the cheat sheet.
 
 
Bean validation (JSR303 aka [http://beanvalidation.org/1.0/spec/ Bean Validation 1.0] /JSR349 aka [http://beanvalidation.org/1.1/spec/ Bean Validaiton 1.1]) is one of the most common ways to perform [https://www.owasp.org/index.php/Input_Validation_Cheat_Sheet input validation] in Java. It is an application layer agnostic validation spec which provides the developer with the means to define a set of validation constraints on a domain model and then perform validation of those constraints through out the  various application tiers.
 
 
 
One advantage of this approach is that the validation constraints and the corresponding validators are only written once, thus reducing duplication of effort and ensuring uniformity:
 
 
 
== Typical Validation ==
 
 
 
https://www.owasp.org/images/d/db/Bean_validation_typical.jpg
 
<br />
 
== Bean Validation ==
 
 
 
https://www.owasp.org/images/6/69/Bean_validation_jsr.jpg
 
 
 
<br />
 
= Setup =
 
 
 
The examples in this guide use Hibernate Validator (the reference implementation for Bean Validation 1.1).
 
 
 
Add Hibernate Validator to your pom.xml :
 
 
 
  <dependency>
 
      <groupId>org.hibernate</groupId>
 
      <artifactId>hibernate-validator</artifactId>
 
      <version>5.2.4.Final</version>
 
  </dependency>
 
 
 
 
 
Enable bean validation support in Spring's context.xml
 
 
 
  <beans:beans ...
 
  ...
 
  <mvc:annotation-driven />
 
  ...
 
  </beans:beans>
 
 
 
For more info, please see the [http://hibernate.org/validator/documentation/getting-started/ setup guide]
 
 
 
<br />
 
 
 
= Basics =
 
 
 
In order to get started using Bean Validation, you must add validation constraints (<code>@Pattern, @Digits, @Min, @Max, @Size, @Past, @Future, @CreditCardNumber, @Email, @URL</code>, etc.) to your model and then utilize the <code>@Valid</code> annotation when passing your model around in various application layers.
 
 
 
Constraints can be applied in several places:
 
* Fields
 
* Properties
 
* Classes
 
 
 
For the sake of simplicity all the examples below feature field constraints and all validation is triggered by the controller. Refer to the Bean Validation documentation for a full list of examples.
 
 
 
When it comes to error handling, the Hibernate Validator returns a <code>BindingResult</code> object which contains a <code>List<ObjectError></code>. The examples below feature simplistic error handling, while a production ready application would have a more elaborate design that takes care of logging and error page redirection.
 
 
 
<br />
 
 
 
= Pre-defined Constraints =
 
 
 
== @Pattern ==
 
 
 
'''Annotation''': <code>@Pattern(regex=,flag=)</code>
 
 
 
'''Data Type''': CharSequence
 
 
 
'''Use''': Checks if the annotated string matches the regular expression regex considering the given flag match
 
 
 
[http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch02.html#section-builtin-constraints Reference]
 
 
 
'''Model'''
 
 
 
  import org.hibernate.validator.constraints.Pattern
 
 
 
  public class Article {
 
 
 
    //Constraint: Alpha Numeric article titles only
 
    //https://www.owasp.org/index.php/OWASP_Validation_Regex_Repository for useful regex's
 
   
 
    @Pattern(regexp = "[a-zA-Z0-9 ]")
 
    private String articleTitle;
 
     
 
    public String getArticleTitle() {
 
        return articleTitle;
 
    }
 
 
 
    public void setArticleTitle(String articleTitle) {
 
    this.articleTitle = articleTitle;
 
    }  
 
   
 
    ...
 
   
 
  }
 
 
 
 
 
'''Controller''' 
 
 
 
  import javax.validation.Valid;
 
  import com.company.app.model.Article;
 
 
 
  @Controller
 
  public class ArticleController {
 
 
 
  ...
 
 
 
  @RequestMapping(value={"/postArticle", method={RequestMethod.POST})
 
  public @ResponseBody String postArticle(@Valid Article article, BindingResult result, HttpServletResponse response){
 
 
 
    if(result.hasErrors()){
 
    String errorMessage = "";
 
  response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 
  List<ObjectError> errors = result.getAllErrors();
 
 
 
  for( ObjectError e : errors){
 
  errorMessage+= "ERROR: " + e.getDefaultMessage();
 
  }
 
  return errorMessage;
 
    }
 
 
 
    else{
 
    return "Validation Successful";
 
  }
 
      }
 
  }
 
<br />
 
== @Digits ==
 
 
 
'''Annotation''': <code>@Digits(integer=,fraction=)</code>
 
 
 
'''Data Type''': BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number
 
 
 
'''Use''': Checks whether the annotated value is a number having up to integer digits and fraction fractional digits
 
 
 
[http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch02.html#section-builtin-constraints Reference]
 
 
 
'''Model'''
 
 
 
  import org.hibernate.validator.constraints.Digits
 
 
 
  public class Customer {
 
 
 
        //Constraint: Age can only be 3 digits long or less
 
  @Digits(integer=3, fraction=0)
 
  private int age;
 
 
 
    public String getAge() {
 
    return age;
 
    }
 
 
 
    public void setAge(String age) {
 
    this.age = age;
 
    }
 
   
 
    ...
 
  }
 
 
 
 
'''Controller'''
 
 
 
  import javax.validation.Valid;
 
  import com.company.app.model.Customer;
 
 
 
  @Controller
 
  public class CustomerController {
 
 
 
  ...
 
 
 
  @RequestMapping(value={"/registerCustomer", method={RequestMethod.POST})
 
    public @ResponseBody String registerCustomer(@Valid Customer customer, BindingResult result, HttpServletResponse response){
 
 
 
    if(result.hasErrors()){
 
    String errorMessage = "";
 
  response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 
  List<ObjectError> errors = result.getAllErrors();
 
 
 
  for( ObjectError e : errors){
 
  errorMessage+= "ERROR: " + e.getDefaultMessage();
 
  }
 
  return errorMessage;
 
    }
 
 
 
    else{
 
    return "Validation Successful";
 
  }
 
      }
 
  }
 
<br />
 
== @Min / @Max ==
 
 
 
'''Annotation''': <code>@Min(value=), @Max(value=)</code>
 
 
 
'''Data Type''': BigDecimal, BigInteger, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the character sequence is evaluated), any sub-type of Number
 
 
 
'''Use''': Checks whether the annotated value is higher/lower than or equal to the specified minimum
 
 
 
[http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch02.html#section-builtin-constraints Reference]
 
 
 
'''Model'''
 
 
 
  import org.hibernate.validator.constraints.Min
 
  import org.hibernate.validator.constraints.Max
 
 
 
  public class Review {
 
 
 
        //Constraint: Review rating must be between 1 and 5
 
      @Min(1)
 
      @Max(5)
 
      private int reviewRating;
 
 
 
      public int getReviewRating() {
 
      return reviewRating;
 
      }
 
 
 
      public void setReviewRating(int reviewRating) {
 
      this.reviewRating = reviewRating;
 
    }
 
 
 
  ...
 
  }
 
 
 
 
 
'''Controller'''
 
 
 
  import javax.validation.Valid;
 
  import com.company.app.model.ReviewRating;
 
 
 
  @Controller
 
  public class ReviewController {
 
 
 
  ...
 
 
 
  @RequestMapping(value={"/postReview", method={RequestMethod.POST})
 
      public @ResponseBody String postReview(@Valid Review review, BindingResult result, HttpServletResponse response){
 
 
 
    if(result.hasErrors()){
 
    String errorMessage = "";
 
  response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 
  List<ObjectError> errors = result.getAllErrors();
 
 
 
  for( ObjectError e : errors){
 
  errorMessage+= "ERROR: " + e.getDefaultMessage();
 
  }
 
  return errorMessage;
 
    }
 
 
 
    else{
 
    return "Validation Successful";
 
  }
 
      }
 
  }
 
<br />
 
== @Size ==
 
 
 
'''Annotation''': <code>@Size(min=, max=)</code>
 
 
 
'''Data Type''': CharSequence, Collection, Map and arrays
 
 
 
'''Use''': Checks if the annotated element’s size is between min and max (inclusive)
 
 
 
[http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch02.html#section-builtin-constraints Reference]
 
 
 
'''Model'''
 
 
 
  import org.hibernate.validator.constraints.Size
 
 
 
  public class Message {
 
   
 
          //Constraint: Message must be at least 10 characters long, but less than 500
 
    @Size(min=10, max=500)
 
    private String message;
 
 
 
    public String getMessage() {
 
    return message;
 
    }
 
 
 
    public void setMessage(String message) {
 
    this.message = message;
 
    }
 
   
 
    ...
 
  }
 
 
 
 
 
'''Controller'''
 
 
 
  import javax.validation.Valid;
 
  import com.company.app.model.Message;
 
 
 
  @Controller
 
  public class MessageController {
 
 
 
  ...
 
 
 
  @RequestMapping(value={"/sendMessage", method={RequestMethod.POST})
 
      public @ResponseBody String sendMessage(@Valid Message message, BindingResult result, HttpServletResponse response){
 
 
 
    if(result.hasErrors()){
 
    String errorMessage = "";
 
  response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 
  List<ObjectError> errors = result.getAllErrors();
 
 
 
  for( ObjectError e : errors){
 
  errorMessage+= "ERROR: " + e.getDefaultMessage();
 
  }
 
  return errorMessage;
 
    }
 
 
 
    else{
 
    return "Validation Successful";
 
  }
 
      }
 
  }
 
<br />
 
== @Past / @Future ==
 
 
 
'''Annotation''': <code>@Past, @Future</code>
 
 
 
'''Data Type''': java.util.Date, java.util.Calendar, java.time.chrono.ChronoZonedDateTime, java.time.Instant, java.time.OffsetDateTime
 
 
 
'''Use''': Checks whether the annotated date is in the past / future
 
 
 
[http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch02.html#section-builtin-constraints Reference]
 
 
 
'''Model'''
 
 
 
  import org.hibernate.validator.constraints.Past
 
  import org.hibernate.validator.constraints.Future
 
 
 
  public class DoctorVisit {
 
 
 
        //Constraint: Birthdate must be in the past
 
      @Past
 
      private Date birthDate;
 
 
 
      public Date getBirthDate() {
 
      return birthDate;
 
      }
 
     
 
      public void setBirthDate(Date birthDate) {
 
      this.birthDate = birthDate;
 
      }
 
 
 
        //Constraint: Schedule visit date must be in the future
 
      @Future
 
      private String scheduledVisitDate;
 
 
 
      public String getScheduledVisitDate() {
 
      return scheduledVisitDate;
 
      }
 
 
 
      public void setScheduledVisitDate(String scheduledVisitDate) {
 
      this.scheduledVisitDate = scheduledVisitDate;
 
      }
 
     
 
  ...
 
  }
 
 
 
 
 
'''Controller'''
 
 
 
  import javax.validation.Valid;
 
  import com.company.app.model.DoctorVisit;
 
 
 
  @Controller
 
  public class DoctorVisitController {
 
 
 
  ...
 
 
 
  @RequestMapping(value={"/scheduleVisit", method={RequestMethod.POST})
 
      public @ResponseBody String scheduleVisit(@Valid DoctorVisit doctorvisit, BindingResult result, HttpServletResponse response){
 
 
 
    if(result.hasErrors()){
 
    String errorMessage = "";
 
  response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
 
  List<ObjectError> errors = result.getAllErrors();
 
 
 
  for( ObjectError e : errors){
 
  errorMessage+= "ERROR: " + e.getDefaultMessage();
 
  }
 
  return errorMessage;
 
    }
 
 
 
    else{
 
    return "Validation Successful";
 
  }
 
      }
 
  }
 
<br />
 
== Additional Constraints ==
 
 
 
In addition to providing the complete set of JSR303 constraints, Hibernate Validator also defines some additional constraints for convenience:
 
 
 
* <code>@CreditCardNumber</code>
 
* <code>@EAN</code>
 
* <code>@Email</code>
 
* <code>@Length</code>
 
* <code>@Range</code>
 
* <code>@SafeHtml</code>
 
* <code>@ScriptAssert</code>
 
* <code>@URL</code>
 
 
 
http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch02.html#table-custom-constraints
 
<br />
 
= Custom Constraints =
 
 
 
One of the most powerful features of bean validation is the ability to define your own constraints that go beyond the simple validation offered by built in constraints.
 
 
 
Creating custom constraints is beyond the scope of this guide. Please see http://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch06.html
 
<br />
 
= Author =
 
 
 
Anton Abashkin - abashkin.anton [at] gmail.com
 
<br />
 
= Other Cheatsheets =
 
{{Cheatsheet_Navigation_Body}}
 
 
 
[[Category:Cheatsheets]]
 

Latest revision as of 13:56, 15 July 2019

Cheatsheets-header.jpg

The Cheat Sheet Series project has been moved to GitHub!

Please visit Bean Validation Cheat Sheet to see the latest version of the cheat sheet.