How can I prevent user from entering HTML or Java script tags in input type in Spring MVC? There should be a server side validation. I am working on a project with thousands of JSPs and controllers. How can I do this?
If you want a server side solution, you could implement a redirect filter that eliminates everything that contains javascript tags and javascript code. Another way is to check the input values in the controller's method that is associated with it.
You probably have to redesign a few things. First, you should always validate the user input twice: once client-side, once server-side.
Thus, you will need to validate the user input in your JavaScript code (using a Regexp probably), and to validate it again in your Java code.
If your application follow the usual design patterns, your controller receives a DTO as a parameter to the entry-point. There you can use the #Valid annotation and add all the necessary rules on the fields of your DTO (using javax.validation annotations).
While there may be many possible answers, one of them is using JSR 303 validator framework.
You can include hibernate validator to use JSR 303 framework.
First step is applying different type of constraint on your class. For example
example taken from : Hibernate Validator - Reference - 1.2. Applying constraints
package org.hibernate.validator.referenceguide.chapter01;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Car {
#NotNull //manufacturer must never be null
private String manufacturer;
#NotNull
#Size(min = 2, max = 14) //licensePlate must never be null and must be between 2 and 14 characters long
private String licensePlate;
#Min(2)
private int seatCount; //seatCount must be at least 2
//getters and setters ...
}
Now in your controller, use #Valid annotation to validate your car object and also pass a BindingResult parameter, that will validate whether this object is valid or not
#Controller
#RequestMapping("/car")
public class CarController {
#RequestMapping(value = "/newcar", method = RequestMethod.POST)
public String addCustomer(#Valid Car car, BindingResult result) {
if (result.hasErrors()) {
//car data is not valid, enter data again
return "AddNewCar.jsp";
} else {
//save car logic here
return "CarSavedSuccessfully.jsp";
}
}
}
Related
Here my controller:
#PutMapping("{id}")
public Mono<QdCFPresenter> save(
Long id,
#RequestBody #Valid #NotNull QdCFPresenter qdcf
) {
return this.qdcfService.store(qdcf);
}
I need to validate that id and qdcf.id are equals.
The way I need to accomplish that is using javax.validation.
We have all validation rules all encapsulated using javax.validation validations.
For example:
public class QdCFPresenter {
private Long id;
#NotNull
private Long codi;
}
So, is there any way to get it USING javax.validation validations?
I need to validate that id and qdcf.id are equals.
I would disagree with this statement.
I would suggest to separate the concepts and have 3 different classes:
an incoming request DTO (QdCFPresenter in your case), it shouldn't contain id as it is a part neither of POST nor PUT request
a domain model (with id and code)
an outgoing response DTO (also with id and code)
Two last ones look similar but have different responsibilities. The response DTO is your contract with consumers, it could maintain its documentation and so on. The domain model is your internal thing and shouldn't be exposed to be able to evolve if required.
And the incoming request DTO is a blueprint for the creation or modification. You shouldn't require it to have id at all.
For example in rust, we can use type-safe json! macro like this:-
let value = json!({
"user": json!({
"data" : json!({"
filled": false
})
})
});
What is the similar way in java without creating POJO or string literal?
In spring, you normally don't need lines like your RUST-example. Spring is doing a lot behind the scenes for you.
Two common use-cases
1. Provide a REST-API
Normally, when you use spring, then you want to build a REST-API. A simple API looks like this:
// User.java
#Data // <- Lombok annotation, which creates getter/setter/equals/hashcode for us
public class User {
private String name;
}
// UserController.java
#Controller
#RequiredArgsConstructor
#RequestMapping("/users")
public class UserController {
private final UserRepository userRepository;
#GetMapping("/{id}")
public User getUser(#PathVariable("id") String id) {
// spring will serialize the user automatically for you
// there is no need to build a json yourself
return userRepository.getById(id);
}
2. Consume a REST-API
On the other hand, we want to consume a REST-API. But also here: Spring and his ecosystem is doing the JSON-part for you.
// User.java
#Data
public class User {
private String name;
}
// some random method in a class with a webClient
private User consumeRest() {
// even here: no manual json parsing at all
// Spring-magic is working for you
return this.webClient.get()
.uri(someUriHere)
.retrive()
.bodyToMono(User.class)
.block();
}
tl;dr
Spring (and java) requires a strong typing. You need almost always a type-class (aka POJO). The classes can be really complex. Hundred of fields and nested fields? No problem.
There are some "hacks" to bypass the type. Like the link in the comments or a Map<String, Object> but you will loose the type-safety.
If that is too much "boilerplate", than Java is not perhaps the right choice for you.
I'm looking for a way to export some JPA entities to a REST API, but instead of sending the whole entity every time I want to share just some specific fields depending of the entry point. Here's a small example:
Say we have an Author class with few fields:
#Entity
public class Author implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = SEQUENCE)
private Long id;
#NotNull
#Size(min = 1, message = "{required.field}")
private String name;
#NotNull
#Size(min = 1, message = "{required.field}")
private String country;
private LocalDate birthDate;
// getters and setters
}
And say we have this REST service (just two methods):
#Path("authors")
public class AuthorREST {
#Inject
private AuthorBC bc;
#GET
#Produces("application/json")
public List<Author> find(#QueryParam("q") String query) throws Exception {
List<Author> result;
if (Strings.isEmpty(query)) {
result = bc.findAll();
} else {
result = bc.find(query);
}
return result;
}
#GET
#Path("{id}")
#Produces("application/json")
public Author load(#PathParam("id") Long id) throws Exception {
Author result = bc.load(id);
if (result == null) {
throw new NotFoundException();
}
return result;
}
}
Now, this way, I'll always have the 4 fields when my API is called.
I understand that if I use Jackson I can set an #JsonIgnore to fields I want to ignore, and they will always be ignored.
But what if I want that, in some cases, my whole entity is returned by one service, and in other service (or other method in the same service), only 2 or 3 fields are returned?
Is there a way to do it?
#JsonView and mix-in
You already know you can use annotations such as #JsonIgnore and #JsonIgnoreProperties to make Jackson ignore some properties.
You also could check the #JsonView annotation. For some details on how to use #JsonView with JAX-RS, have a look here.
If modifying the JPA entities is not an option, consider mix-in annotations as described in this answer.
Data Transfer Object
Data Transfer Object (DTO) is a pattern that was created with a very well defined purpose: transfer data to remote interfaces, just like webservices. This pattern fits very well in REST APIs and using DTOs you'll have more flexibility in the long run. You can have tailored classes for your needs, once the REST resource representations don't need to have the same attributes as the persistence objects.
To avoid boilerplate code, you can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.
For details on the benefits of using DTOs, check the following answers:
Why you should use DTOs in your REST API
Using tailored classes of request and response
To give better names to your DTOs, check the following answer:
Giving meaningful names to your DTOs
If you want to decouple the parsing from your JPA entities and return only certain attributes you can always use Mixins for this purpose.
http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html
https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations
One more thing. If you want things to be dynamic in one service to return one representation in another to return another representation. Your option is to write a custom JSON serializer!
Check this post for how to create a customer serializer:
How do I use a custom Serializer with Jackson?
For myself I found it quite suitable to use #JsonView annotation. So you can define fields to be rendered in specific view. You can find more info here http://wiki.fasterxml.com/JacksonJsonViews
I think you can write a custom MessageBodyWriter using Jersey framework and you can control the response payload the way you want. Here you have to write few lines of code in-order to manage the response payload. For more information please visit https://jersey.java.net/documentation/latest/message-body-workers.html#d0e6826
I would use Spring Data REST and then use the ApiModel annotation to hide the attributes you do not want exposed.
I know about #Valid notations in the Controller and adding different validations on my POJO object. But what about primitive data types like integers and Characters how to perform validations on them. I don't won't to create a different function or anything like that for validation. I want to use some already existing validation framework for spring. And my other problem is that if I include various validations in my POJO. Then my validation might change depending on my requirement.(i.e consider a USER pojo sometimes my request mapping might make the Id field Not Null sometime it can be null). Is there a way to separate validations from code. And depending on requirement feed the validations through an xml as in struts validation framework. Consider the following example to understand better.
Part 1 of my question:
public class User {
#NotNull
private String name;//Sometimes I would not have any value on this.
//Sometimes I might have some value on this
#NotNull
private int Id;
}
/*This might require a non-null value for user*/
#RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, #Valid #ModelAttribute("user") User user, BindingResult result){
if (result.hasErrors()){
// do something
}
else {
// do something else
}
}
/*This won't require a compulsory name values*/
#RequestMapping(value="/user", method=RequestMethod.POST)
public createUser(Model model, #Valid #ModelAttribute("user") User user, BindingResult result){
if (result.hasErrors()){
// do something
}
else {
// do something else
}
}
Part 2 of my question:
//How do I validate userId in this situation?
#RequestMapping(value = "/{userId}", method = RequestMethod.GET)
User view(#PathVariable String userId){
//do something
}
How do I carry on such validations and validations for primitive types using Spring validation framework without having to create a validation class?
Part 2 In my opinion validation should be done on a service rather than on the controller. You may have some issues like this one here when validation of some arguments does not work. Probably if you add another param that is not marked as #PathVariable your validation will work. This is because you are working here on a proxy of proxy of proxy rather than a concrete component. Moving validation to services gives you some more flexibility and in my opinion a better design. In my project I do validation of primitive types as well and it work 100% with no issues.
I have a Website model, that has a #Required User owner property. This property gets filled inside the controller method. However, validation is checked upon entering the controller method, so it considers the object invalid (because at the time, it is).
Should Play! validation be used for this purpose?
Should I just drop the #Valid annotation and check manually using validation.required(website)?
Update - using validation.required(website) only validates that the website is not null, but it does not run validate any of the annotations on the website. If I'm not using the #Valid parameter annotation, does this mean I can't use annotation-based validations on the model itself? What's a programmer to do?
Update2 - it seems I should be calling validation.valid(website) instead of validation.required(website). I also added a #Required annotation to the add() method parameter (instead of #Valid). Is this the way it should be done?
#Entity
public class Website extends PortalModel {
#Required
public String url;
#Required
#ManyToOne
public User owner;
}
public class Sites extends UserAwareControllerBase {
public static void added(#Valid Website website) {
website.owner = getUser(); // from base class
if (Validation.hasErrors()) {
Validation.keep();
params.flash();
add();
}
websiteRepo.save(website);
edit(website.id);
}
}
I'm not sure if there's a point to declare User as #Required if your app's users have no influence on it. Well, it's a safety net for your own code.
But since the user is not in the parameters when you submit the website form, you have to validate manually:
website.owner = getUser();
validation.valid(website);
...