I have a requirement where I need to use role based access to service methods. I have restful services and i use spring-data to interact with MongoDB.
There are some of the restrictions that I have. I deal with a document in DB called "Organization". In each organization, I know who are the Admins. I do not have a repository of users who can access the services.
So the only way I can enforce some access based rules is to check if the logged in user is one of the admin's configured for each organization and then allow the user to access the methods.
Should I think of applying Spring security in this case? Otherwise will a simple check on user against the configured admins in the database document help? Can I make this check at a single point so that I can apply it to service methods based on my use case needs.
Please provide your suggestions / thoughts on how to go about this.
If you use Spring Security your rest methods can take advantage of a passed-in authenticated Principal object (example here) whereupon you can do whatever extra validation desired (such as checking if the admin is good for the given organization requested, etc.) There are many other parameters also available, perhaps allowing for this org checking to be done once and stored in the session object.
I have a pretty common Spring Web MVC application using Hibernate. The user of the application are stored in a table called USER and there also username, password and a couple of other properties are stored. Also I am using Spring security with jdbc-user-service in order to secure the application so that only user from this table can access is with their username / password.
Now my problem is that once logged on, I need to access this user object quite often, e.g. in order to get all orders from this user, the address of this user and so on. I know how to access the Principal object, which shares username with my User Object, but I am wondering which would be the best strategy to easily access my custom User object. There are a couple of strategies like putting it in the session, write a findUserByUsername() method and call it whenever needed (which would result in hitting the database quite a lot I think) but I am looking for a smarter way. Is it somehow possible to inject a User object? Or should I rather put it in the session? If so, how would be the best way to achieve this? How could I hook in after the Spring frameworks login event?
Any suggestions?
Thanks
Paul
You could always scope a UserDetails bean to the session (link). This would, of course, be a stateful bean, so you would be free to store any information about your User entity that you need to and access it as long as the session is active. One trip to the database.
Note: The User object (and any related objects) will be detached from the Hibernate Session. Keep this in mind when either 'storing' the values within the bean or accessing them in later processing.
I am building a multi-tenant site with MVC3. Prior to this project I had never touched either the .NET stack or web development in general, so as you can imagine my domain knowledge is somewhat lacking.
I'm still using the default AccountController architecture, but I pretty quickly determined that I didn't want to use aspnetdb.mdf for authentication, as its design is pretty different from my requirements. I do want role-based authentication, so I ultimately wrote custom User and Role classes as code-first Entity classes and used this tutorial to set up a custom MembershipProvider and RoleProvider.
Everything works fine at the moment, but as I'm building the multi-tenancy functionality it's getting messier. Based on this example, I am using a custom extension of Controller which keeps track of which tenant is using this session, and all my controllers extend this class instead of the base Controller class.
All tenants are using the same database. Each entity has a Tenant property that identifies who it belongs to.
So, here's the problem:
Usernames do not need to be globally unique. Only the combination of username and tenant must be unique. Thus, ValidateUser needs to know the username, password, and tenant. Since my custom MembershipProvider is not a Controller, it doesn't know which tenant is using the session, and the ValidateUser method only accepts username and password so I can't pass it that information.
Furthermore, pretty much everything MembershipProvider does besides ValidateUser is already implemented in a UserRepository class, which that tutorial told me to make. I'm rather fond of the Repository pattern, and it's way more convenient than adhering to MembershipProvider's interface, but now there's a massive conflict of interest between UserRepository and MembershipProvider.
So, my question:
Do I need to use MembershipProvider, or even Membership, at all?
It seems like everything MembershipProvider does would be performed more conveniently by my repository class. At this point all I'd have to do is write a new Authorize attribute that doesn't rely on Membership, and everything should work without any MembershipProvider at all, right? If I don't drop Membership I'm forced to completely mutilate my MembershipProvider implementation to the point that it barely resembles the original interface anyway.
...Either that or Membership does a ton of things I'm unaware of and removing it is blatant stupidity. That is also a distinct possibility.
No, you don't need to use Membership, but consider for a moment exactly what Membership is. Membership does not involve your users names, or addresses, or other information. Membership is strictly related to the login account of the system. It only handles details with creating, validating, updating, or deleting the information needed to login. That's it.
Likewise, the Role system is only assigning a role name to the user.
Ultimately, Membership and Roles are just implementations of the IPrincipal interface. While FormsAuthentication is an implementation of the IIdentity interface. These work together so that you can utlize the built-in ASP.NET Authorization and Authentication system.
Membership actually does have the concept of multiple tennants. This functionality is accomplished via the "ApplicationNane" field of the aspnet_users table (also settable in the Membership class itself)
From the documentation on the Membership class:
The ApplicationName is used to identify users specific to an application. That is, the same user name can exist in the database for multiple ASP.NET applications that specify a different ApplicationName. This enables multiple applications to use the same database to store user information without running into duplicate user name conflicts. Alternatively, multiple ASP.NET applications can use the same user database by specifying the same ApplicationName. The ApplicationName can be set programmatically or declaratively in the configuration for the Web application.
Now, this is designed to typically be set in the Web.Config and stay the same for the life of the app, but I see no reason why you can't use it to specify which tennant you want.
The only issue here is that Membership.ApplicationName is static, which means it's shared by all threads running in the App Pool. However, if you use some kind of lock around accessing it, then this shouldn't be a huge issue (though it could affect scalability at some level).
This would basically allow you to use the standard, out of the box membership provider without any changes. You just have ot make sure to guard the access calls.
You don't have to use the membership provider at all. Its simply provided as a quick and consistent way to get up and running. Some choose it because it supports multiple databases (universal membership providers include azure as well as sql ce, express, and full) but for others trying to map it to your applications rules can be more difficult than the <5 lines of code it takes to authenticate and issue your own forms auth ticket.
With that said I'm assuming you are using forms authentication. You can simply issue the ticket yourself. I would still program against an interface for this which the default MVC template should have, so simply add in a new tenant id.
With that said, I'd consider having unique names. It ensures you don't 'forget' to do an additional tenant check somewhere else in the app and tenant1\userBip and tenant2\userBip surprisingly end up stomping on each others record at some point.
True, testing should uncover this - if testing is complete : )
I'm using Spring Security which works great to make sure that a user has a certain role before accessing a resource. But now I need to verify something a little different:
`/product/edit/{productId}`
What is the best way to verify that the logged in user "owns" productId? My business mappings handle the relationship (a user has a list of products). I need to verify this product belongs to the user and hence, they can edit it.
I know how to gain access to productId and the logged in user in both the controller and an interceptor. I don't believe this logic belongs in the controller at all. The interceptor seems better but I wondered if Spring Security had an "accepted" way of handling this situation.
Yes, in Spring you can implement this by implementing Access Control Lists. ACL declaration specifies permissions for individual objects per user. Once you have everything setup like acl entries in your database and logic, you can use SpEL and #PostFilter annotation to control the list of objects returned to a user.
Spring Security Documentation
Related:
I am using a Security scheme that is based on session attributes. I know that Spring has Acegi Security but I don't have much time to study that module. I just want to share this to solicit comments.
The pseudocode is like this.
On successful Login, I am setting an attribute on user session. The object that I am placing as session attribute is a simple javabean with a map of privileges.
public class UserInfo{
public String getRole(){};
public Map checkPrivilege(){};
//getters and setters
}
The session attributes contains the Role also of the user. (He could be a User/Guest/Admin/Super Admin). Now there are certain privileges that are authorized to User.
For my JSP, I just check out the user session for his role and privilege.
My rough code is like this using JSTL
IF (User Info in Session is 'User' and has this privilege)
Add Button is shown
Else
No Add Button is shown.
I have these questions:
Are session attributes considered secure that no one else can sniff or hack?
Are security based on these scheme considered secure-enough?
Session attributes are stored on the server side only, so yes they are secure.
There is no problem with putting these security identifiers into session attributes in terms of security. But that is the easy part of web application security! The hard part is the rest of the security infrastructure, which I am concerned that you have not thought about yet.
I recommend you investigate Spring Security.