Java bean validation with validation proxy and JAXB - java

I have a REST service whose data entity beans are annotated with JAXB annotations. For security reasons those entity beans need to be validated. To see the differences I wan't to switch on and off this validation, hence I thought to create a bean validation proxy. But I don't know how I can tell the JAXB provider to use the CategoryValidationProxy instead of the CategoryImpl. Because of the already existing XSD schema validation, a propper MessageBodyReader for dataEntity Category already exists. This MessageBodyReader looks like: Validate JAXBElement
[EDIT :]
Right now I have done all the data validation within the data entity implementation itself. So there is no way to switch this validation on and off. Enable and disable it on the fly is quite important because this enables me to see which attacks can be prevented.

Related

Securing JSON-PATCH paths in Spring Boot Data Rest application

I'm using a pretty vanilla spring-boot-starter-data-rest setup and enabled the PATCH method. All is working, but I have a security concern and wonder what's the recommended way of mitigating it.
The problem is that PATCH paths allow reachable entities to be updated from a different endpoint. So, suppose I have a comments endpoint and an article endpoint. Each comment has a to-one association with its article. A user that has permission to edit a comment could then do something like this:
PATCH http://some.domain.foo/api/comments/1234
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/article/title", "value": "foobar2" }
]
and thereby change the title of the article !!
Clearly this ain't good.
In this case, for other parts of the API the association to the "article" needs to be traversable. But it must be read-only.
So... how do I accomplish this in Spring?
Intercept the request?
Implement a handler method?
Write my own Controller from scratch ?
Thanks!
Seems that current implementation on spring-data-rest converts paths to SpEL to apply values directly on beans. See PatchOperation (v2.5.x).
Consider these options:
Instead of json-patch use json-merge PATCH request to send partial updates (with "application/json" or "application/merge-patch+json" content type). This will respect #JsonIgnore and other Jackson annotations and also treat associations differently.
You can disable "json-patch+json" completely, for example by adding a security filter
You can always create your custom json-patch implementation, if you still need it
Use application-level joining not relying on JPA, i.e. only exposing IDs of the linked entities and providing custom links in your ResourceProcessor.
Additionally, if you're using JPA and Comment.article is annotated with #ManyToOne make sure that there's no cascading on association. Even if the article object is modified with patch it won't be saved together with the comment.
There's been a recent fix in Spring Data Rest:
https://github.com/spring-projects/spring-data-rest/issues/2177
The commit that resolves this issue is:
https://github.com/spring-projects/spring-data-rest/commit/5d0687d1a1bb9a84264ecb4cd088907837c382d3
From a quick read this seems to be checking that when applying a JSON patch to an entity a check is done with Jackson that the path should be accessible (read/write).
This should prevent users from being able to specify paths in the JSON patch that aren't normally exposed through POST/GET requests that are mapped directly onto entities through Jackson. I think that if you had marked the article as readable from the comment and the title attribute as writeable then the new code should allow it. Or that's I think what org.springframework.data.rest.webmvc.json.patch.JsonPointerMapping#verify is trying to do.
So if you marked the article on the comment as not being readable through Jackson (#JsonIgnore on the getter) then JSON patch shouldn't allow the title of the article to be set through a comment. The association would still exist, just not be exposed through JSON serialization, I'm not sure if this would cause problems for your application.
The change is released in Spring Data Rest 4.0.0 which is part of Spring Data 2022.0.1 which is in Spring Boot 3.0.2.
https://github.com/spring-projects/spring-data-rest/releases/tag/4.0.0
https://github.com/spring-projects/spring-data-bom/releases/tag/2022.0.1
https://github.com/spring-projects/spring-boot/releases/tag/v3.0.2

Spring and JSR303

I need to validate an XML coming from a vendor and saving it as XML type in oracle....
Now i need a process to trigger a validation engine... which is going to validate it and save the value in indicator as 'YES' or 'NO' example if the address in XML doesn't exist in our dB make the address indicator as 'NO' [which we correct in another process...]
I already used JSR303 in Spring 303, which is very effective and easy to use....but it uses a form backing object and #valid.....
Can I use it here in my design...
Or let me put it this way -
Is it possible for Spring's JSR-303 implementation to validate object fields that are not from form input?
I know its a very vague question...so please let me know if I need to explain more
Most of the work for object's validation performed by JSR-303 provider (hibernate-validator in most cases). Spring's role in this process is minimal -- it just parses user's data, binds it to the object and passes this object to validator. Also, during application startup, Spring creates Validator instance.
So, you can interfere in this proccess: create object, which will be validated, manually, get Validator instance and pass object to him. As result you will get a Set of ConstraintViolation which represents errors of each fields.
In this scheme main problem is that JSR-303 validator works with object, while you operates with XML document. You may deserialize XML document to object, validate it and, if it doesn't have errors, serialize it back to XML and writes to DB.
I recommend to read the following part of Hibernate Validator manual: 2.2. Validating constraints It describe Validator interface and a few useful methods: validate(), validateProperty() and validateValue().
One benefit from Spring here is that you won't need to create Validator by yourself with Validation.buildDefaultValidatorFactory().getValidator(): just #Autowire it as all other Spring beans:
#Autowired
private Validator validator;

Jackson and Hibernate Validator

Are there any online tutorial available to use Hibernate validator with Jackson for validating JSON?
I am using Spring and Jackson now for JSON parsing.
With Spring, I use MappingJacksonHttpMessageConverter to automatically translate the incoming JSON payload to Java object.
I would like to add validator annotations to the Java class. For example, if I have the Person class with "name" as one of the fields, I like to validate the JSON payload if the "name" element appears 1 time. If it appears more than 1 time in the payload, then I like the validator to kick in to reject the request.
Right now what I observed is that if there are multiple names in the payload, Jackson simply ignores and picks up the last one.
The Java object is not bound to any XML schema and the like.
What is the best practice for validating JSON?
Spring has JSR-303 support built in, see this chapter in the reference manual.
If you are using Spring MVC, see here, you should just be able to annotate parameters to #RequestMapping methods with #Valid.

How to handle in spring validation of json request / bean if the json cannot be converted to the bean?

I have classic Spring MVC application.
I want to validate a Form using a corresponding Java Bean, annotated with JSR-303 validation annotation.
The form data is sent by an ajax call using JSON. This Json is converted to the target Java Bean with Jackson - automatically by spring:
#RequestMapping(value = ControllerConstants.CALCULATION_MAPPING_SUBMIT_FORM,method = RequestMethod.POST)
public String submitForm(#Valid #RequestBody MyFormBean bean, final BindingResult result) {
...
}
Problem is for example if I have an Integer field in my bean but, in JSON the values is not a number. In this case it cannot create the target bean, that cannot be validated. This situation cannot be solved with custom property editors, since there is no way to convert a a text that not represents an Integer to Integer.
It seems that this is solved in Grails, we get errors from validator (errors is domain object) which has to be created during the data binding. So I assume spring supports this, thus Grails just uses Spring's support)
So how to elegantly solve this situation to handle this "validation" error?
UPDATE
Actually I figured out, that is this is supported by spring if we use simple form submit. The problem is with integration of Jackson deserialized. It does not fills errors. Still how to solve this?
I see two options...
Have client side validation that would not allow the form to be submitted if the there are formatting issues.
On the server side you will have to have a mechanism of handling the exception that would catch it and report the problem back to client.
Hope that helps.
EDIT:
Well not having client side validations may not be a good user experience. Users do not want to be reminded about validation errors after they have made a server round trip. However, if this is still a constraint have a look at following url and it gives elegant way of handling such issues and reporting informative error messages.
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/

JPA validation strategy

NetBeans let me choose between three values for the JPA validation strategy: Auto, Callback and None. What does "Auto" mean? Does "Callback" mean the use of #PrePersist, #PreUpdate, and #PreRemove?
Is there a performance hit if I use Auto or Callback if there is no validation to perform?
The JPA 2.0 Spec (JSR 317) does not require a Bean Validation (JSR-303) implementation. Validation is optional. Thus, javax.persistence.ValidationMode can take different values:
Auto (default) - if a validation provider is available, then validation should occur
Callback - validation is required and a PersistenceException must be thrown if a provider cannot be obtained
None - no validation should be attempted and the lack of a validation provider should not cause an exception
This should answer all your questions.

Categories

Resources