how do I prevent spring mvc overwriting sessionattributes from request - forms

I have an MVC spring application where the user logs on, this stores a User #SessionAttribute , which I refer to subsequently e.g. when updating a Customer object in a POST request I want the session User info to add to this object.
My problem is when I access the #ModelAttribute("user") User object in the customer POST, spring has bound request parameters into it i.e. the User.name has the value of the Customer.name from the submitted form.
NB I've kind of hacked this in that all controllers are subclasses of my AppController, which is where the #SessionAttributes are declared. But the principle would be the same if it was a single controller.
So can I prevent spring binding form:customer name value to User.name?
(I suspect webflow would be a more suitable framework for this, but don't have the time available right now to rewrite using this)

You can allow or disallow binding of certain fields of your model attributes using #InitBinder:
#InitBinder("user")
public void configureBindingOfUser(WebDataBinder binder) {
binder.setAllowedFields(); // No fields allowed
}
However, I don't think it's a good idea to use #SessionAttributes to store the current user or other similar objects. #SessionAttributes was originally designed to maintain state of form-backing objects between GET and POST requests, not as a general purpose way to access a session.
Perhaps it would be better to use session-scoped beans or custom argument resolvers to access this kind of information.

Related

How to decouple a data core domain from a REST domain?

I am curious on what is the preferred way to decouple a core domain entity from the entity served by a REST layer.
I saw on this enlightening Spring REST tutorial http://spring.io/guides/tutorials/rest/1/ that it's a good thing not to expose the core domain model directly in the REST layer as it should evolve independently of the core domain model.
The core service is handling and producing events. These events are seen as the communication ports of the application. The core service does not see any REST domain entity. And the REST controller does not see any core domain entity.
To make things simpler, let's consider the example of only one entity, the Order entity.
The tutorial shows how an Order REST domain class is passed by a REST request to a controller. In turn the controller creates an OrderDetails entity passed to an Order handling event to create a CreateOrderEvent event, which is then passed to a service which returns another OrderCreatedEvent event. The controller finally creates a REST domain Order entity from the returned event, and sends it in the response.
We can see that for this one entity, there is one class for core domain entity, one class for the REST domain entity, and one class for the event payload entity.
Also, we can see that the events, sitting in the application core, extend on some base events which remind strongly of the HTTP methods. It is a bit surprising to see this REST like stuff seeping into the application core, when what we are trying to do in the first place, is to decouple the application core from the REST layer.
Any thought on this design or an some alternate design ? Are there any preferred way of achieving this decoupling ?
Thanks for any suggestion.
Kind Regards,
Stephane
One additional question I now have...
Should I go for an entity NotFoundException exception or for a notFoundEntity event member in the event, on a REST domain decoupled from the data domain ?
The event sent back to the controller can carry a notFoundEntity member state which can be used in the controller.
Here is the event notFoundEntity logic:
protected boolean notFoundEntity = false;
public boolean isNotFoundEntity() {
return notFoundEntity;
}
public static OneAdminEvent notFound(Long id) {
OneAdminEvent oneAdmiEvent = new OneAdminEvent(id);
oneAdmiEvent.notFoundEntity = true;
return oneAdmiEvent;
}
The service updates the event member state depending on the entity having been found or not:
Admin admin = adminRepository.findOne(deleteAdminEvent.getId());
if (admin == null) {
return AdminDeletedEvent.notFound(deleteAdminEvent.getId());
In the controller, a call to checks for the entity having been found or not:
if (adminDeletedEvent.isNotFoundEntity()) {
}
This is in line with the decoupling design.
But, I'm not sure the decoupling event should carry this information. This information can be seen as an exception, a business custom exception.
Also, using an exception makes it possible to specify a rollback attribute in the transactional annotation:
#Transactional(rollbackFor = NotFoundException.class)
With an exception, the only not found entity logic left is on the service, the event does not contain any.
The service now looks like:
Admin admin = adminRepository.findOne(deleteAdminEvent.getId());
if (admin == null) {
throw new NotFoundException("No admin was found with the id " + deleteAdminEvent.getId());
What rule of thumb to use to decide when to use a member state in the event and when to use a business custom exception ?
It would be harder for this example application to decouple the REST domain and core domain layers more. Not only have the REST (a.k.a. "view") objects been cleanly separated from the core (a.k.a. "domain") objects, but their direct communication has also been decoupled via an internal event-driven architecture. The reason that the core events remind you so strongly of HTTP methods is probably more due to the simplicity of the example's use cases than by necessity or design. Such can be the peril of example. :)
While this is certainly a sound way to layer an application, the real question is whether it's necessary for your particular scenario. If your application will be very data-oriented (e.g., a data entry system with few business rules), you might not need a separate set of REST domain objects (much the way you might decide you don't need a separate layer of "view" objects in a traditional MVC application). You could take the Spring Data REST approach (see Oliver Gierke's RESTBucks sample app). Then again, if you have some heavy business logic in core and want to create a rich domain model, you're probably better off with a more decoupled architecture.

JPA: How to exclude certain fields from loading from database table

i have a class User which holds an email address and password for authentication users in my web application. This user is mapped to the database via JPA / Eclipselink.
My question is, how can i prevent JPA from loading the password field back from the database? Since i will access the user object in my web app, i'm uncomfortable regarding security with sending the password to the browser.
Is there any way i can prevent loading the field in JPA / EclipseLink? Declaring the field transient is not an option, since i want to store it on the database when i call persist() on the user object.
Thanks,
fredddmadison
JB Nizet has a valid point. Retrieving it and serializing it in the Http response are two separate concerns.
I'm not sure what you're using to serialize your data. If it this is a REST API, consider Jackson's #JsonIgnore annotation or Eclipselink MOXy's #XmlTransient equivalent. If this uses Java EL (facelets, jsps), you should be able to select only the bean properties of interest.
If you really must do this during retrieval, consider JPQL's/Criteria API's constructor functionality. Ensure that the object has a constructor that accepts the specified parameters, and keep in mind that it won't be managed in the persistence context if it's retrieved in this manner.
SELECT NEW my.package.User(u.id, u.name, u.etc) FROM User u
Alternatively, consider the #PostLoad lifecycle callback.
#PostLoad
private void postLoad() {
this.password = null;
}
Finally, this might not be the case, but I would like to reinforce the notion that passwords shouldn't be stored in plaintext. I mention this because returning a hashed salted password that used a secure algorithm (bCrypt, multiple iteration SHA-512, etc) wouldn't be that big a deal (but still isn't ideal).
I have the similar problem. But in my case I have many #OneToMany relationships inside of Entity class and some of them are EAGER. When I query against this Entity it loads all of them, although for web service I need only some of them.
I tried TupleQuery. But it's not the solution because to get needed OneToMany relationships I have to join and get many duplicate rows of the main query. It makes the result more heawy, than economic.

Refactoring application: Direct database access -> access through REST

we have a huge database application, which must get refactored (there are so many reasons for this. biggest one: security).
What we already have:
MySQL Database
JPA2 (Eclipselink) classes for over 100 tables
Client application that accesses the database directly
What needs to be there:
REST interface
Login/Logout with roles via database
What I've done so far:
Set up Spring MVC 3.2.1 with Spring Security 3.1.1
Using a custom UserDetailsService (contains just static data for testing atm)
Created a few Controllers for testing (simply receiving/providing data)
Design Problems:
We have maaaaany #OneToMany and #ManyToMany relations in our database
1.: (important)
If I'd send the whole object tree with all child objects as a response, I could probably send the whole database at once.
So I need a way to request for example 'all Articles'. But it should omit all the child objects. I've tried this yesterday and the objects I received were tons of megabytes:
#PersistenceContext
private EntityManager em;
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody List<Article> index() {
List<Article> a = em.createQuery("SELECT a FROM Article a", Article.class).getResultList();
return a;
}
2.: (important)
If the client receives an Article, at the moment we can simply call article.getAuthor() and JPA will do a SELECT a FROM Author a JOIN Article ar WHERE ar.author_id = ?.
With REST we could make a request to /authors/{id}. But: This way we can't use our old JPA models on the client side, because the model contains Author author and not Long author_id.
Do we have to rewrite every model or is there a simpler approach?
3.: (less important)
Authentication: Make it stateless or not? I've never worked with stateless auth so far, but Spring seems to have some kind of support for it. When I look at some sample implementations on the web I have security concerns: With every request they send username and password. This can't be the right way.
If someone knows a nice solution for that, please tell me. Else I'd just go with standard HTTP Sessions.
4.:
What's the best way to design the client side model?
public class Book {
int id;
List<Author> authors; //option1
List<Integer> authorIds; //option2
Map<Integer, Author> idAuthorMap; //option3
}
(This is a Book which has multiple authors). All three options have different pros and cons:
I could directly access the corresponding Author model, but if I request a Book model via REST, I maybe don't want the model now, but later. So option 2 would be better:
I could request a Book model directly via REST. And use the authorIds to afterwards fetch the corresponding author(s). But now I can't simply use myBook.getAuthors().
This is a mixture of 1. and 2.: If I just request the Books with only the Author ids included, I could do something like: idAuthorMap.put(authorId, null).
But maybe there's a Java library that handles all the stuff for me?!
That's it for now. Thank you guys :)
The maybe solution(s):
Problem: Select only the data I need. This means more or less to ignore every #ManyToMany, #OneToMany, #ManyToOne relations.
Solution: Use #JsonIgnore and/or #JsonIgnoreProperties.
Problem: Every ignored relation should get fetched easily without modifying the data model.
Solution: Example models:
class Book {
int bId;
Author author; // has #ManyToOne
}
class Author {
int aId;
List<Book> books; // has #OneToMany
}
Now I can fetch a book via REST: GET /books/4 and the result will look like that ('cause I ignore all relations via #JsonIgnore): {"bId":4}
Then I have to create another route to receive the related author: GET /books/4/author. Will return: {"aId":6}.
Backwards: GET /authors/6/books -> [{"bId":4},{"bId":42}].
There will be a route for every #ManyToMany, #OneToMany, #ManyToOne, but nothing more. So this will not exist: GET /authors/6/books/42. The client should use GET /books/42.
First, you will want to control how the JPA layer handles your relationships. What I mean is using Lazy Loading vs. Eager loading. This can easily be controller via the "fetch" option on the annotation like thus:
#OneToMany(fetch=FetchType.Lazy)
What this tells JPA is that, for this related object, only load it when some code requests it. Behind the scenes, what is happening is that a dynamic "proxy" object is being made/created. When you try to access this proxy, it's smart enough to go out and do another SQL to gather that needed bit. In the case of Collection, its even smart enough to grab the underlying objects in batches are you iterate over the items in the Collection. But, be warned: access to these proxies has to happen all within the same general Session. The underlying ORM framework (don't know how Eclipselink works...I am a Hybernate user) will not know how to associate the sub-requests with the proper domain object. This has a bigger effect when you use transportation frameworks like Flex BlazeDS, which tries to marshal objects using bytecode instead of the interface, and usually gets tripped up when it sees these proxy objects.
You may also want to set your cascade policy, which can be done via the "cascade" option like
#OneToMany(cascade=CascadeType.ALL)
Or you can give it a list like:
#OneToMany(cascade={CascadeType.MERGE, CascadeType.REMOVE})
Once you control what is getting pulled from your database, then you need to look at how you are marshalling your domain objects. Are you sending this via JSON, XML, a mixture depending on the request? What frameworks are you using (Jackson, FlexJSON, XStream, something else)? The problem is, even if you set the fetch type to Lazy, these frameworks will still go after the related objects, thus negating all the work you did telling it to lazily load. This is where things get more specific to the mashalling/serializing scheme: you will need to figure out how to tell your framework what to marshal and what not to marshal. Again, this will be highly dependent on whatever framework is in use.

How to do role-based access control for a franchise business?

I'm building the 2nd iteration of a web-based CRM+CMS for a franchise service business in ASP.NET MVC 2. I need to control access to each franchise's services based on the roles a user is assigned for that franchise.
4 examples:
Receptionist should be able to book service jobs in for her "Atlantic Seaboard" franchise, but not do any reporting.
Technician should be able to alter service jobs, but not modify invoices.
Managers should be able to apply discount to invoices for jobs within their stores.
Owner should be able to pull reports for any franchises he owns.
Where should franchise-level access control fit in between the Data - Services - Web layer?
If it belongs in my Controllers, how should I best implement it?
Partial Schema
Roles class
int ID { get; set; } // primary key for Role
string Name { get; set; }
Partial Franchises class
short ID { get; set; } // primary key for Franchise
string Slug { get; set; } // unique key for URL access, eg /{franchise}/{job}
string Name { get; set; }
UserRoles mapping
short FranchiseID; // related to franchises table
Guid UserID; // related to Users table
int RoleID; // related to Roles table
DateTime ValidFrom;
DateTime ValidUntil;
Controller Implementation
Access Control with [Authorize] attribute
If there was just one franchise involved, I could simply limit access to a controller action like so:
[Authorize(Roles="Receptionist, Technician, Manager, Owner")]
public ActionResult CreateJob(Job job)
{
...
}
And since franchises don't just pop up over night, perhaps this is a strong case to use the new Areas feature in ASP.NET MVC 2? Or would this lead to duplicate Views?
Controllers, URL Routing & Areas
Assuming Areas aren't used, what would be the best way to determine which franchise's data is being accessed? I thought of this:
{franchise}/{controller}/{action}/{id}
or is it better to determine a job's franchise in a Details(...) action and limit a user's action with [Authorize]:
{job}/{id}/{action}/{subaction}
{invoice}/{id}/{action}/{subaction}
which makes more sense if any user could potentially have access to more than one franchise without cluttering the URL with a {franchise} parameter.
Any input is appreciated.
Edit:
Background
I built the previous CRM in classic ASP and it runs the business well, but it's time for an upgrade to speed up workflow and leave less room for error. For the sake of proper testing and better separation between data and presentation, I decided to implement the repository pattern as seen in Rob Conery's MVC Storefront series.
How to arrange services and repositories?
It makes sense to have a JobService that retrieves any service jobs based on available filters, eg. IQueryable<Job> GetJobs();. But since a job can only belong to one franchise, a function like IQueryable<Job> GetJobs(int franchiseID); could belong in either FranchiseService or in JobService. Should FranchiseService act as a CatalogService (like in MVC Storefront)?
Let me take a stab at answering this. I am in the process of playing with a sample app that touches some of the aspects mentioned. This is not an authoritative answer, merely experience.
Where should franchise-level access control fit in between the Data - Services - Web layer?
This access restrictions should
permeated through your application at
two levels 1) the database 2) the
application layer. In an MVC context I
would suggest having creating a custom
Authorization attribute - this handles
the security between the Web-Services
layer. I would have this attribute do
two things
Get the current roles allowed for the user (either from the DB of it may
be stored in the user session)
Do the checking to see if the user is part of the allowed list of roles.
With regards to the database, this
depends on how you are storing the
data, one database for all franchises
or database per franchise. In the
first case there are several ways to limit
and setup access restrictions for
data to a particular
franchise.
Since franchises don't just pop up over night, perhaps this is a strong case to use the new Areas feature in ASP.NET MVC 2? Or would this lead to duplicate Views?
I think that Areas should be used to
split and group functionality. If you
were to use Areas to split franchises,
this is where I see a duplication of
views, controllers etc. occurring. Duplicate
views can be overcome by using a
custom view engine to specifically
overriding the way MVC locates your
views. Plug: See my answer to ASP.NET MVC: customized design per domain
Assuming Areas aren't used, what would be the best way to determine which franchise's data is being accessed?
As mentioned above, you could the
users session to store basic
information such as the franchise the
user belongs to and the roles etc
assigned. I think the rule I read
somewhere goes along the lines of
"Secure your actions, not your
controllers"
Create you routes etc for the norm and
not for the exception. eg. Is there
currently a business case that says a
user can have access to more than one
franchise?
How to arrange services and repositories?
Have a set of base services or base
classes that will contain all the
information required for a particular
franchise such as the franchiseId.
Th main issue that it does resolve is
that your service methods are cleaner
not having the franchiseId argument.
The repository however may need this
value since as some point you need to
disambiguate the data you are
requesting or storing (assuming one db
for all franchises). However, you
could overcome some of this using IoC.
The downside I see is that
they there will always be calls to the
database every time your objects are
creating (i.e. if the franchise
route were to be used, you would need
to go the database to obtain the
corresponding franchiseId every time
you create a service object. ( I might
be mistaken on this one, since the IoC
containers do have some LifeStyle
options that may be able to assist and
prevent this) You could have
a list of Franchises that are created
on you Application start that you
could use to map your route values to
obtain the correct information. This
part of the answer is scattered, but
the main thing is that IoC will help
you decouple a lot of dependencies.
Hope this helps..

RIA Services and Linq2Sql

I have a Product object with a property that is a collection of type Workflows. In my "GetProducts" method on the domaincontext object I have set a breakpoint at the return statement to see if the workflows collection is filled.
It is.
On the client side I check Context.Products[0].Workflows in another breakpoint and I see 0 results. Is there a way to persist this nested data for consumption on the client side or is RIA Services inhibited from doing this?
If you have or can download the RiaServicesOverviewPreview.pdf document section 4.8 details how to do this. The basic summary it.
Make sure your L2S query specifies the .LoadWith<>() parameter. Lazy loading doesn't work with RIA services so you have to use implicit loading.
You need to apply the "IncludeAttribute" to the associated member. For example add the [Include] attribute on your Workflows field in the Product metadata class.
Ensure that your Workflow (child) type is exposed as a client type so it gets genned to the client side.
You can get the document here: http://www.microsoft.com/downloads/details.aspx?FamilyID=76bb3a07-3846-4564-b0c3-27972bcaabce&displaylang=en
I should kick myself. I realized that I needed to add "[Include]" to the property in Product within the DataService.metadata.cs file and now it gets sent to the client.