Enabling Mandatory Validation while fetching Data from database using Spring JPA with Hibernate - spring

I am developing an application using Spring JPA 2.0 with Hibernate as a ORM provider. We have only read only access to database and will generate report. I would like do some validation while fetching data.
#Column(name = "LOGICAL_ID", nullable = false)
#NotNull
private Long logicalId;
I added Hibernate validator which implements JSR 303 specs. But while fetching it doesn't throw any runtime exception or ConstraintViolationException? Do i add something in the configuration or am i missing something? Please advice me.

Like i've posted in Implementing cross-validation in java
You can use the following piece of code to validate an entity manually;
ValidatorFactory factory = Validation.byDefaultProvider().configure().traversableResolver(new CustomTraversableResolver() ).buildValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<YourBaseClass>> constraintViolations = Validator.validate(myEntityToValidate);
If you would like this to be done for you automatically, it might be that the 'javax.persistence.validation.mode' property is set to none (http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/configuration.html).
I prefer the manual validation though, since then you have control and details, of which constraints are not passing.

Related

#Valid #Payload on #KafkaHandler – bug or missing feature?

We use Spring Kafka together with Spring Boot (all latest versions). We switched handling of Kafka messages into #KafkaHandler annotated methods and expected that #Valid/#Validated together with #Payload will ensure payload validation, but that did not happen. This feature is working for #KafkaListener, should it be also working for #KafkaHandler?
#KafkaListener(...)
#Component
public class NotificationListener {
#KafkaHandler
public void handleV1(#Payload #Valid NotificationV1 notification) {
Thank you.
The Validator is not applied in this case because we just don't reach the PayloadMethodArgumentResolver for that purpose.
The target payload for the multi-method #KafkaListener is resolved before we call the method because we definitely need to know which method to call. Such a logic is done in the InvocableHandlerMethod.getMethodArgumentValues():
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
...
try {
args[i] = this.resolvers.resolveArgument(parameter, message);
}
The Validator functionality is done in those resolvers. The findProvidedArgument() gives us the payload converted before for execution and here we just don't check any annotations on parameters.
We probably need to poll validation logic into the DelegatingInvocableHandler when we have selected a handler and before its invocation...
Feel free to raise a GitHub issue so we don't forget that this is needed to be addressed somehow.
The reason that why #KafkaListener works with #Valid annotation is that it just like a restful controller endpoint, which is the entrance of the service. The team works to add support for validation working on these situations, and it can be found that this validation mechanism is added in 2018.
As for #KafkaHandler, I'm not that familiar with spring-kafka, but if the validation just not work, it just means that the team doesn't add support for this situation. I recommend you to use the Spring Boot Method Validation Feature, which works fine for all spring managed beans and all the standard validation annotations such as #Size. One last thing, be careful about the exception thrown while validation fails.

Hibernate ColumnTransformer and DataJpaTest

I do have a mysql database. That database reads and writes by hibernate and uses field encryption. The application is running on spring boot.
#ColumnTransformer(
read = "AES_DECRYPT(message, 'secret')",
write = "AES_ENCRYPT(?, 'secret')"
)
#Column(
columnDefinition = "varbinary(5120)"
)
private String field;
When writing unit tests I get an exception because these test is running on embedded h2 and the encryption methods are mysql based.
#RunWith(SpringRunner.class)
#DataJpaTest
I found this solution, but it does not work for me: How to Ignore Certain Fields in unit tests, Hibernate
Is there any way to test this behaviour and ignoring encryption and decryption in test configuration?
regards,
Moritz

Vulnerability warning with XStreamMarshaller

When using a XStreamMarshaller with spring batch, I get the following message:
Security framework of XStream not initialized, XStream is probably vulnerable.
First try: According to the documentation, I've tried to reset all permissions, but I still have the same message. Besides, I have no security error when parsing XML files... So I think that this code just doen't work. Here's a sample of code:
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.getXStream().addPermission(NoTypePermission.NONE);
Second try: I have also tried with the setSupportedClasses method, but it doesn't work either (I still get the vulnerability message and not supported classes are still unmarshelled correctly):
XStreamMarshaller marshaller = new XStreamMarshaller();
marshaller.setSupportedClasses(FooBar.class);
How can I set security permissions with XStreamMarshaller?
Note: according to this thread, the Security Framework was introduced with 1.4.7 and it is still not mandatory.... But it will be mandatory for XStream 1.5.0!
Version of XStream used: 1.4.10
Version of Spring Batch used: 4.0.1
For information, I'm using Spring Boot (but I'm not sure it's relevant here)
Solution for the 'First Try':
The reason why it didn't work is that XStreamMarshaller instantiates a xstream object with afterPropertiesSet without checking if one have already been created, so we can't use getXStream() in a #Bean method. To make this work, we can for example set security config while injecting the marshaller in another bean:
#Configuration
public class JobSecurityConfig {
public JobSecurityConfig(XStreamMarshaller marshaller) {
XStream xstream = marshaller.getXStream();
XStream.setupDefaultSecurity(xstream);
xstream.allowTypes(new Class[]{Bar.class});
}
}
Another solution: extend XSreamMarshaller
You can also extend XStreamMarshaller and override only the customizeXStream() method to set security configuration.
#Override
protected void customizeXStream(XStream xstream) {
XStream.setupDefaultSecurity(xstream);
xstream.allowTypes(new Class[]{Bar.class});
}
Why the 'Second Try' doesn't work:
setSupportedClasses is only used on marshalling!!.. StaxEventItemReader doesn't care about supported classes!
Xstream website have provided details about the Security Framework Security Framework.
below method are provided to set Security permissions
XStream.addPermission(TypePermission);
XStream.allowTypes(Class[]);
XStream.allowTypes(String[]);
XStream.allowTypesByRegExp(String[]);
XStream.allowTypesByRegExp(Pattern[]);
XStream.allowTypesByWildcard(String[]);
XStream.allowTypeHierary(Class);
XStream.denyPermission(TypePermission);
XStream.denyTypes(Class[]);
XStream.denyTypes(String[]);
XStream.denyTypesByRegExp(String[]);
XStream.denyTypesByRegExp(Pattern[]);
XStream.denyTypesByWildcard(String[]);
XStream.denyTypeHierary(Class);
You can also refer this Tutorial
I hope this helps
From the official spring docs:
By default, XStream allows for arbitrary classes to be unmarshalled,
which can lead to unsafe Java serialization effects. As such, it is
not recommended to use the XStreamMarshaller to unmarshal XML from
external sources (i.e. the Web), as this can result in security
vulnerabilities.
You're using Spring's abstraction XStreamMarshaller to interface with the XStream library. By default the library can marshall/unmarshall arbitrary classes (including from external web source).
If you are not doing that (working with classes from external web sources) you can simply ignore the message.
If you want to remove the message follow what's recommended in Spring's official doc (linked above) and XStream website (security config example).
It boils down to setting up supported classes to make sure only the registered classes are eligible for unmarshalling.
This property is empty by default, which means - support all classes - hence the warning message you're getting.

How to obtain getUserPrincipal().getUserName() while implementing Spring Data JPA AuditorAware interface

I'm trying to use Spring Data JPA (1.6.2) in my current project. All seems to work well, but I got stuck while implementing the AuditorAware interface.
My application will be deployed to an old Apache Jetspeed JSR168 compliant portal. This portal takes care of user authentication/authorisation. As such, I don't have to use a security framework like Spring Security or Shiro. The other frameworks in my application are:
Struts 1.2.4 (with a Struts-Portal-Bridge)
Spring 3.2.10
JPA (Hibernate 3.6.10 as ORM provider)
I'd like to use #CreatedBy and #LastModifiedBy annotated fields in my entities (I got #CreatedDate and #LastModifiedDate working). In my application I usually obtain the username using request.getUserPrincipal().getUserName().
But how can I get hold of the username while implementing the AuditorAware interface?
The example implementation from the Spring Data JPA docs:
class SpringSecurityAuditorAware implements AuditorAware<User> {
public User getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return ((MyUserDetails) authentication.getPrincipal()).getUser();
}
}
Somehow I want to implement AuditorAware like this:
class MyAuditorAware implements AuditorAware<String> {
public String getCurrentAuditor() {
return <<principal from servlet- or portletcontext>>.getUserName();
}
}
How can I accomplish this without adding an additional framework?
As Konstantin already mentioned in his comment, you probably want to save the principal name in a scope suitable for a request. This may very well be a ThreadLocal. This allows you to get it easily later on in your AuditorAware implementation.
To stay with Spring's naming call it PrincipalContextHolder. As a starting point you may look at the source of JodaTimeContextHolder for a simple implementation of a ContextHolder.

update of hibernate and spring security failed

I would like to update hibernate 3 to 4 and spring 3 to 3.1 and spring security 3 to 3.1 in my application, but when I do this the users with authorities generated using previous versions within database are not usable and the exception
java.io.InvalidClassException GrantedAuthorityImpl local class incompatible
occurred when the application want to fetch users' authorities from database. This is the config for entity user:
#ElementCollection(targetClass = GrantedAuthority.class, fetch=FetchType.EAGER)
#CollectionTable(name = "user_authorities", schema = "mydb", joinColumns = #javax.persistence.JoinColumn(name = "user_id"))
private Collection<GrantedAuthority> authorities;
Just checked differences between master and 3.0.x branches. Your problem is in the serialization which is done by Hibernate. Judging on the JPA configuration you are storing serializable POJOs (GrantedAuthorityImpl) objects directly in to the database. That is not optimal approach. Better would be to change this to store just collection of strings.
Workaround: You can put the old GrantedAuthorityImpl source in you sources so that the classloader will prefer your version. Then you should be OK with Spring Security 3.1 and still use your approach. However that is from the hack solutions category.

Resources