Protect data for spring-data-rest - spring

I am using Spring Data Rest to expose JPA repositories to our React front-end application.
And I also use Spring Security and JWT to protect REST APIs.
For examples, we have Entity and Repository as below:
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
....
}
public interface CustomerRepository extends PagingAndSortingRepository<Customer, Long> {
}
Spring Data Rest will expose CustomerRepository to REST endpoint /api/customers
So our React application can call REST endpoints to get data. It works well.
However, someone with valid JWT token can use tools like Postman to fetch all customers data from the servers. Of course, we don't want this happen.
My questions:
How can we prevent such abnormal usage?
What's the best practice to use Spring Data Rest?

Your application exposes a REST API by using Spring Data REST. One of your entities is a Customer entity which is exposed through the CustomerRepository. On querying the list of all entities by calling /api/customers you only want those Customer entities to be listed that the querying principal has permission to see.
This can be done by annotating the method in question with #PreFilter or #PostFilter as explained in the Spring Security reference documentation. You need to specify some sort of condition.
An example:
#PostFilter(hasPermission(filterObject, 'read'))
public List<Customer> findAll();
Mind that #PostFilter iterates through the returned value, which can take some time, depending on the size of the returned list.

Related

Use jpa and mongo repositories based on #profiles in Spring Boot MVC application

I am very new to spring and mongo db.Please suggest the way for my problem: I have this web app written in Spring boot and it mainly uses JPA for database. I have a multiple entity and then I have multiple repositories that extends JPARepository with some methods that fetch data from the database.
But now I need to have a second database and it must be MongoDB. Everything is identical to the JPA, but now I have a new repository class, that this time extends MongoRepository.
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
public interface CustomerRepositoryMongo extends MongoRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
So now I have two classes, CustomerRepository and CustomerRepositoryMongo.
1.First of all what all changes i have to made to run it in a mongodb inside the eclipse Ide and how can i configure mongodb inside eclipse IDE.?
2.How can i easily switch between two dbs,how to specify which repository to used?
3.I have no idea how can i achieve this also i can not have both the interfaces with the same name.
4.I have tried the jpa approach with #profile annotation,its working fine..but to use the mongodb ,i have to create the collection for all the entities which has #table ,#entity annotation.So shall i use #document annotation as well to specify the collection name because i am using the different names in my queries.

Call service from Repository in spring boot

Am new to Spring boot, i have seen example where we create repository to perform various operarion with the given Object. here is the sample one
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
so from the rest client if i send People jason
http://localhost:8080/people{ .... }
it inserts to the Database, internally it calls save method.
Here after calling from the REST client , i want to do some validation or business login and then insert to the database, how can i do it? It means i want to call a service method to do all the business logic and then insert so how can i call service method from repository class?
This repository is an interface and will allow you to perform various operations (here operations means DB related operations) involving Person objects. It gets these operations by extending the PagingAndSortingRepositry interface defined in Spring Data Commons.
At runtime, Spring Data REST will create an implementation of this interface automatically. Then it will use the #RepositoryRestResource annotation to direct Spring MVC to create RESTful endpoints at /people.
I don't think your requirements can be fulfilled with having the "#RepositoryRestResource" on the repository. You may want to create a proper sprint-boot application with the api, service and repo layer to perform the tasks you want to perform.

Spring Data Rest integration with Spring HATEOAS

From various documents and tuts, I've earned and learned following points so far:
Spring Data Rest (SDR) used for exposing our Spring Data Repository as REST service, so that one can use it for self exploring, without any need of creating JAXRS manually. It only works for Repository layer, and we cannot control its way of working in terms of modification or addition other than the configuration using RepositoryRestMvcConfiguration. It uses Spring HATEOAS internally somewhere.
Spring HATEOAS is made for creating links within Entities we return through Controller or REST endpoints. We got ResourceSupport to extend our entity or Resource wrapper class to wrap our Entity to create or add links. There are several Annotations and classes to use such as #EnableHyperediaSupport and EntityLinks.
There may be some points which I am yet to explore or get to know about, but I was just curious about How can we combine SDR into HATEOAS link building process ? Say for eg.
EntityBean bean = repository.findByName(name);
Resource<EntityBean> resource = new Resource<EntityBean>(bean);
//JaxRsLinkBuilder.linkTo(TestResource.class).withRel("entity") // this also works
//ControllerLinkBuilder.linkTo(TestResource.class).withRel("myRel") // this also works
// I am curious how ControllerLinkBuilder and JaxRSLinkBuilder both are working for JaxRS.
//Here TestResource is my REST service class. now in below line:
resource.add(JaxRsLinkBuilder.linkTo(MyRepository.class).withRel("sdf")); //not working
// MyRepository is SDR exposed repository, which I thought should work but not working.
return resource;
So, I just wanted to include my exposed REST repository into manual HATEOAS link building process.. is it possible to do so ?
You should able to use Spring-HATEOAS ResourceProcessor to build links.
Example:
#Component
public class MyBeanResourceProcessor implements ResourceProcessor<Resource<MyBean>> {
#Autowired
private EntityLinks entityLinks;
public Resource<MyBean> process(Resource<MyBean> resource) {
MyBean mybean = resource.getContent();
// Do your linking here using entity class
//EntityBean bean = repository.findByName(name);
//Resource<EntityBean> resource = new Resource<EntityBean>(bean);
// assuming you are linking to a single resource and bean.getId() method... check entitylinks for other methods
//resource.add(entityLinks.linkForSingleResource(bean.class,bean.getId()).withRel("sdf"));
return resource;
}
}

Separating repository and implementation in Spring-Data

Given some abstract entity:
public interface Person{
long getID();
String getFirstName();
String getLastName();
}
And repository to work with this entity:
public interface PersonRepository {
void save(Person person);
Person findOne(long id);
}
I want to implement above repository with different technologies: MongoDB with Spring Data MongoDB, Jpa with Spring Data JPA and for example Cassandra with my own implementation of repository. Can somebody point me on documentation about implementing own Spring Data module?
How can I use Spring Data concepts to use both existed solutions and create my own implementation?
It will be great if you can provide simple example.
There's already a module for Cassandra in the making, so I suggest to contact the maintainers and help out if you like to. Other than that, most of the community driven modules have started by simply studying the existing modules and working their way backwards.

Spring data - Manual implementation

Is it possible to write my own function implementation along usage of spring repositories?
I would like to actually implement the function
getUserByFirstName()
and not get it automagically.
While i still want to get
getUserById()
automagically from spring-data.
1) is it possible?
2) is it possible to achieve logging for all methods spring data automagically generates? (or should i write them manually with
logger.log("entering method ...");
See section 1.3 of the manual for the first requirement:
http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.single-repository-behaviour
For the second requirement I guess some AOP based solution might work for you well here. See here for example using Spring's AOP support:
logging with AOP in spring?
Yes, you can!!!
There is an amazing feature in Spring data that allows this:
Create an interface with your custom method:
public interface UserRepositoryCustom {
User getUserByFirstName();
}
Make your Spring Data interface extends this new interface, as well as the Spring data crud interface (or JPA, Mongo or whatever spring data interface you're extending):
public interface MySpringDataRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
}
Create a class that implements only your custom interface. The name of the class must be Impl, for instance: UserRepositoryImpl:
public class MySpringDataRepositoryImpl implements UserRepositoryCustom {
public User getUserByFirstName(){
//Your custom implementation
}
}
Now, you only need to inject the Spring data repository in your service and you can use both methods: the spring-data implemented method and your custom implemented method:
#Inject private MySpringDataRepository myRepository;
That's it!!
Look at this section in the documentation:
Spring Data Custom implementations

Resources