Spring MVC 3 - Binding parameters to backing object - java

I am trying to setup an edit form for my User object. I have automatic binding from the form to the user object working fine.
I'm wondering how do I prevent malicious users from binding to fields of my User object that I don't want them to?
For example, my user object has userName, and it also has points. When they click edit user, I want them to be able to change the userName, but not the points. A malicious user could just send an extra points=429429 as a hidden field in the form by editing the HTML, and this would automatically be bound to the backing object by Spring.

I would suggest separating your front-end code from the logic for what will be saved in the database. The form backing object is just meant to be a simple object that captures want the user has done in the view... it shouldn't be used to save directly to the database. I would have a Service layer handle the decision on whether or not to update certain fields... the controller should just receive the input and pass it along. This way, the service can decide what fields should be updated.
public void updateUser(long userId, User updatedUser) {
User currentUser = dao.getCurrentUserById(userId);
currentUser.userName = updatedUser.username;
//...... update anyother fields....
dao.SaveUser(currentUser);
}
or you could define the method in a way that the caller knows what will be updated:
public void updateUser(long userId, String updatedUsername);
I would also argue that this is a lot easier to unit test if this logic is in the Service Layer.
Hope this helps

Add this to your controller:
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.setAllowedFields("field1", "field2");
}

Related

Spring Security w/ Nested Accounts

I'm having difficulties with authorizing nested accounts in Spring Security. I'm new to Spring Security. I spent around a week to reach a working solution, but it's an ugly one and I'd love to refactor it...
I'm using Spring 4.2.4 and Spring Security 4.0.3.
I have user accounts that look like this:
Office User A
Office User B
Field User C
--> Field Sub-User a
--> Field Sub-User b
Field User D
--> Field Sub-User c
So, an office user has only one account, but a field user has at least one sub-account always, with the potential for two or more sub-accounts. Each sub-account can have different authorities. Like one sub-account can view only, and another sub-account can view plus create.
The user will sign-in with an account (A, B, C, or D). If A or B signs in, there is no issue. However, if user C signs in, they need to pick (a or b) and we need information for their choice. If user D signs in, we need information for user (c). I'm using Spring Security and struggling with getting the information for User a/b/c above. I came to a solution, but it's not ideal, and I'd like to know a more proper way.
My solution:
In the #AuthenticationPrincipal implementation of UserDetails, add below code:
private Collection<GrantedAuthority> authorities;
private String uniqueId1;
private String uniqueId2;
public void setAuthorities(Collection<GrantedAuthority> authorities) {
this.authorities = authorities;
}
public Collection<GrantedAuthority> getAuthorities() {
if (this.authorities != null) {
return this.authorities; //CHILD
}
return super.getAuthorities(); // (SUPER)
}
public void setUniqueId1(String uniqueId1) {
this.uniqueId1 = uniqueId1;
}
public String getUniqueId1() {
if (this.uniqueId1!= null) {
return this.uniqueId1; //CHILD
}
return super.getUniqueId1(); // (SUPER)
}
public void setUniqueId2(String uniqueId2) {
this.uniqueId2 = uniqueId2;
}
public String getUniqueId2() {
if (this.uniqueId2!= null) {
return this.uniqueId2; //CHILD
}
return super.getUniqueId2(); // (SUPER)
}
Then, in my method to get logged-in user information, accept a string of the selected user and do like such:
public #ResponseBody FullUserDetails getLoggedInUserInfo(
#AuthenticationPrincipal MyImplementationOfUserDetails user,
String selectedUsername)
MyImplementationOfUserDetails user2 = getUserInfo(selectedUsername);
user.setAuthorities(user2.getAuthorities());
user.setUniqueId1(user2.getUniqueId1());
user.setUniqueId2(user2.getUniqueId2());
In this way, I am able to 'change' the authorities and unique id properties which would otherwise be unchangeable because they are private in the parent classes and normally only accessible through a constructor. I tried making a new constructor in the UserDetails implementation, but when I create a new #AuthenticationPrincipal, it doesn't override the one in the session. I think a new constructor would be the most proper way to go. How do I override the #AuthenticationPrincipal in the session with a new UserDetails object? Or is there a better approach entirely, which I'm not thinking of? I just want the new authorities and unique ID information for the sub-user that was selected to be put into the #AuthenticationPrincipal. The next time I get the #AuthenticationPrincipal, it will then have that information.
The consequences of not getting the new information and putting it in the #AuthenticationPrincipal is that the webpage behavior will be wrong. Mostly because the authority levels will not be correct for the user that was selected.
I was trying to call:
SecurityContextHolder.getContext().setAuthentication(newAuthenticationObjectHere);
But I wasn't seeing the changes after calling setAuthentication()...
The only way I was able to see the changes was by directly calling setters in the MyImplementationOfUserDetails object retrieved from the #AuthenticationPrinciple.
Sorry, very confused, but the main idea is almost understandable.
I think you go in cycles with an idea to calculate all complex relations between accounts and after that to give the final account required permission and provide access to some resource.
What if to change the logic of providing access to resources without manipulating the account relations? And the very important chain - to use remote/distributed Authorization server like Spring OAuth2 one? With it, you can have authorities for any account AND scopes (!). Depending on organization conditions an account can have different scopes. And your final resources (usually they are controllers methods) have pre-authentication by scope. According to this idea, you can separate the logic of providing access based on specific of accounts, implementing all logic in DB with accounts.
Maybe it's the wrong idea for your project, for me it works - I change scopes for customers depending their conditions, but not manipulate with their data and relations in runtime.

Best way to pass a POJO to a spring MVC controller

I have done a few MVC controllers now and used the spring form tags to pass data back and forth but I realise now my actual understanding is a little thin. In my current case I could actually just send the response as url parameters but there are about 15 and I would prefer to send it as a pojo if possible.
My actual question... is ... is it possible to set up a spring style model attribute in a jsp without the attribute having been passed in and without using the form tags ?
So for example something along the lines of
//Pojo
Class personclass
{
private String name + getters and setters
private String address + getters and setters
private String phone + getters and setters
...
}
////first mvc call
#RequestMapping ("/")
Public ModelAndView LandingPage()
{
// no mention of Person pbject
Return mandvobject;
}
//jsp page
//This is the question!
SET ModelAttribute that wasn't passed in to the page
personclass = X
//New MVC call without a submit
window.open ("/NewMVCCall")
//New mvc call
#RequestMapping ("/NewMVCCall")
Public void newMVCPage(#ModelAttribute ("pc") personclass pc, Model model)
{
//process pc object
}
Or am I missing the point and I would have to send it as a json string parameter? Sorry my grasp of this is pretty rudimentary and I'm not sure whether I could quite easily set my own http form content or whether it is because I have used Spring form objects so far that I haven't grasped the complexity of what is going on behind the scenes (i.e form tags converting pojos to json and so on) ?
Many thanks if anyone has the time to set me on the right path...
I am not sure if I am understood your question correctly but you can link a Model to your controller without having to manually pass it to a the view every time you need it, spring will take care of that:
in your Controller :
public class MyController{
#ModelAttribute("pc")
public PersonneClass getPersonnelClass(){
return new PersonneClass();
}
#RequestMapping ("/NewMVCCall")
Public void newMVCPage(#ModelAttribute ("pc") personclass pc, Model model)
{
//process pc object
}
//other methods
}
It is a good practice to stick to java conventions when naming classes so
(personneClass ) must start with an uppercase (PersonneClass) .

GWT - how to set an entry point method for all incomming requests in RPC servelet

I have a RemoteServiceServlet class implements several services (methods).
All the methods need to check the session and get the corresponding user info before doing anything. Since the class have more than 20 service methods, doing so in every service is a nightmare. Is there a way to run some session checking method automatically for all the incoming requests? Or how can I solve this problem?
Here is an example pseudo-code for my situation.
public class OnboardingServiceImpl extends RemoteServiceServlet implements OnboardingService {
private String checkSessionAndGetUser(){...}
public void service1(){
// check session
// get user and do something based on the user data
}
public void service2(){
// check session
// get user and do something based on the user data
}
public void service3(){
// check session
// get user and do something based on the user data
}
...
public void service20(){
// check session
// get user and do something based on the user data
}
}
As you can see, service1, service2, ..., service 20 all need to get the user info based on the session, but I do not want to repeat writing the code for every service. Any help will be appreciated.
I'd suggest to override processCall(RPCRequest rpcRequest)
#Override
public String processCall(RPCRequest rpcRequest) throws SerializationException {
//your checks here, in case of error:
//return RPC.encodeResponseForFailedRequest(null, new Exception("Invalid session"));
// note that you'll have to use a serializable exception type here.
return super.processCall(rpcRequest);
}
RemoteServletServlet's doPost is final, but not service, so you can put your code there.
…or use a servlet filter.
This will however be done outside the "RPC" (before the request is even decoded), so response cannot just be a "throw exception and have it passed to onFailure on client side".
For that, you'll have to either use aspect-oriented programming (such as AspectJ) to "inject" code into all your methods, or call an init method at the beginning of each method (you'll keep repeating the code, but that could possibly be reduced to a one-liner).

How to avoid anemic data model? Can repositories be injected into entities?

I have an immutable User entity:
public class User {
final LocalDate lastPasswordChangeDate;
// final id, name, email, etc.
}
I need to add a method that will return information if the user's password must be changed i.d. it has not been changed for more than the passwordValidIntervalInDays system setting.
The current approach:
public class UserPasswordService {
private SettingsRepository settingsRepository;
#Inject
public UserPasswordService(SettingsRepository settingsRepository) {
this.settingsRepository = settingsRepository;
}
public boolean passwordMustBeChanged(User user) {
return user.lastPasswordChangeDate.plusDays(
settingsRepository.get().passwordValidIntervalInDays
).isBefore(LocalDate.now());
}
}
The question is how to make the above code more object oriented and avoid the anemic domain model antipattern? Should the passwordMustBeChanged method be moved to User if so how to access SettingsRepository, should it be injected into User's constructor, or should a Settings instance be provided to the ctor, or should the passwordMustBeChanged method require a Settings instance to be provided?
The code of Settings and SettingsRepository is not important, but for completness, here it is:
public class Settings {
int passwordValidIntervalInDays;
public Settings(int passwordValidIntervalInDays) {
this.passwordValidIntervalInDays = passwordValidIntervalInDays;
}
}
public class SettingsRepository {
public Settings get() {
// load the settings from the persistent storage
return new Settings(10);
}
}
For a system-wide password expiration policy your approach is not that bad, as long as your UserPasswordService is a domain service, not an application service. Embedding the password expiration policy within User would be a violation of the SRP IMHO, which is not much better.
You could also consider something like (where the factory was initialized with the correct settings):
PasswordExpirationPolicy policy = passwordExpirationPolicyFactory().createDefault();
boolean mustChangePassword = user.passwordMustBeChanged(policy);
//class User
public boolean passwordMustBeChanged(PasswordExpirationPolicy policy) {
return policy.hasExpired(currentDate, this.lastPasswordChangeDate);
}
If eventually the policy can be specified for individual users then you can simply store policy objects on User.
You could also make use of the ISP with you current design and implement a PasswordExpirationPolicy interface on your UserPasswordService service. That will give you the flexibility of refactoring into real policy objects later on without having to change how the User interacts with the policy.
If you had a Password value object you may also make things slightly more cohesive, by having something like (the password creation date would be embedded in the password VO):
//class User
public boolean passwordMustBeChanged(PasswordExpirationPolicy policy) {
return this.password.hasExpired(policy);
}
just to throw out another possible solution would be to implement a long-running process that could do the expiration check and send a command to a PasswordExpiredHandler that could mark the user with having an expired password.
I have stumbled upon a document that provides an answer to my question:
A common problem in applying DDD is when an entity requires access to data in a repository or other gateway in order to carry out a business operation. One solution is to inject repository dependencies directly into the entity, however this is often frowned upon. One reason for this is because it requires the plain-old-(C#, Java, etc…) objects implementing entities to be part of an application dependency graph. Another reason is that is makes reasoning about the behavior of entities more difficult since the Single-Responsibility Principle is violated. A better solution is to have an application service retrieve the information required by an entity, effectively setting up the execution environment, and provide it to the entity.
http://gorodinski.com/blog/2012/04/14/services-in-domain-driven-design-ddd/

JSP MVC Model 2 Architecture Question

I want to develop a web application and I have access this API. In the API there are methods that allow you to get the userId of the current user via context objects. Maybe I'm overthinking this, but I'm very confused as to where to put my CurrentUserId() method. Does that method go in the controller or the model? I was thinking it goes in the model, but it seems redundant to write a property called "getUserId" to return a string called getUserId().toString(). Is this normal and I'm overthinking or am I correct? My co-worker told me to put the logic in the view, but from everything I've read you never put java code or scriplets in the view. I hope this makes sense.
Also here's a method I wrote to return the userId as a string
protected String CurrentUserId(HttpServletRequest request)
{
ContextManager ctxMgr = ContextManagerFactory.getInstance();
Context ctx = ctxMgr.setContext(HttpServletRequest request);
Id userID = ctx.getUserId();
return userID.toString();
}
It should go to Controller.
Create a utility class having this method as static
Because here HttpServletRequest is this model specific(jsp,servlet) , suppose tomorrow if you want to apply the same model to your desktop application then it would fail so better place is controller.

Categories