Grails Spring Security (get current user) - grails

Is there ever a case for:
def user = User.get(springSecurityService.principal.id)
over
def user = springSecurityService.currentUser
All I can think of is preventing lazy inits or ensuring data you are currently operating on is not stale?

In practical terms, I don't see much difference between these two. I would be inclined to use
def user = springSecurityService.currentUser
Because it's slightly shorter that the other form, it's what the plugin docs recommend, and there might be some additional caching of the user within plugin (beyond the caching already provided by Hibernate).

Well, there is a slight difference between the two. The documentation points this out.
currentUser will always return the domain instance of the currently logged in user.
principal on the other hand, retrieves the currently logged in user's Principal. If authenticated, the principal will be a grails.plugin.springsecurity.userdetails.GrailsUser, unless you have created a custom UserDetailsService, in which case it will be whatever implementation of UserDetails you use there.
If not authenticated and the AnonymousAuthenticationFilter is active (true by default) then a standard org.springframework.security.core.userdetails.User is used.
Hope that helps clear things up.

We just encountered a case where code was using currentUser and failing because there was no User record for the User domain. In our case, principal.username worked because we had a custom UserDetailsService that was creating a GrailsUser on the fly if one didn't exist in the User table.
So the distinction is important.

Related

Get the current session with spring-session

Here's my question: I'm writing a platform which I will be giving to the customers to implement their projects with. So in my platform I have created a SessionService in which I have methods like getCurrentSession, getAttribute, setAttribute, etc. Before spring-session my getCurrentMethod looked like this:
#Override
public HttpSession getCurrentSession() {
if (this.session == null) {
final ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
return attr.getRequest().getSession(true); // true == allow create
}
return this.session;
}
which worked perfectly fine, although it looks ugly and have no backing like redis. Now I want to migrate to spring-session and I was hoping to use the SessionRepository to find the current session of the user, however I can only see a getSession(String id) in there. I believe the id is stored in the cookie, so to use it I will probably have to pass the HttpServletRequest object from my controllers, to my facades, to the service layer which is very near the db layer. This looks like a very bad idea to me, so my question would be: is there any way to get the currentSession near the db layer? One way I would think is to write an interceptor that will be invoked the controllers, which will set the current session in the repository, or the service maybe? I'm just not sure this is the right way to go.
Obtaining the Session Id from Service Layer
You can use the RequestContextHolder to retrieve the session id, set attributes, and remove attributes.
The RequestContextHolder is typically setup using RequestContextListener or RequestContextFilter. Spring Session does NOT work with RequestContextListener because there is no way for Spring Session to wrap the request before the RequestContextListener is invoked.
Unfortunately, this means for Spring Boot applications, RequestContextHolder does not work out of the box. To work around it you can create a RequestContextFilter Bean. See spring-boot/gh-2637 for updates on this issue.
Should I be putting this in session?
Just because it is easy to put a lot of objects in session and it is stored in Redis does not mean it is the right thing to do.
Keep in mind that the entire session is retrieved on every request. So while Redis is fast, this can have a significant impact if there are lots of objects in session. Obviously the implementation can be optimized for your situation, but I think the concept of session generally holds this property.
A general rule of thumb is, "Do I need this object for over 95% of my requests?" (read this as almost all of my requests). If so, it may be a candidate for session. In most cases, the object should be security related if it fits this criteria.
Should I access session id from ThreadLocal in the service layer?
This is certainly open for debate as code is as much of an art as it is a science.
However, I'd argue that you should not be obtaining the session id from thread locale variables throughout your architecture. Doing this feels a bit like obtaining a "Person id" and obtaining the current "Person id" from the HttpServletRequest in a ThreadLocale. Instead, values should be obtained from the controller and passed into your service layer.
Your code does not need changing. It will return the Spring Session session object.
Though it is generally better to inject the HttpSession from the controller, or use session-scoped beans and #SessionAttribute than to have such a session service in the first place.

Custom UserSessionRegistry in Spring web socket implementation for a multi tenant scenario?

I am working with Spring Websocket (4.1.4 release) and using #SendToUser for sending messages to the current user. But I've a problem. Ours is a multi-tenant platform where username is not unique, instead a combination of username and tenant id is unique. The DefaultUserSessionRegistry keeps a map from username to a list of session ids:
private final ConcurrentMap<String, Set<String>> userSessionIds = new ConcurrentHashMap<String, Set<String>>();
which would not work in my scenario. So is there a way I can plugin my custom UserSessionRegistry implementation?
After a code search, the issue seems related to this line.
I found that this class is extended by WebSocketMessageBrokerConfigurationSupport, which is extended by a #Configuration class (DelegatingWebSocketMessageBrokerConfiguration), so you could try to extend it by yourself, like in this example:
https://github.com/arawn/overview-of-spring4/blob/master/src/main/java/jco/conference/oxquiz/WebSocketConfig.java
I had no time to verify this, but if your problem is only the UserSessionRegistry implementation, this could be the way of overriding that #Bean method.
Update:
After digging a bit more, I found the real entry point to the whole flow: search for the DefaultHandshakeHandler class, having the determineUser method (I cannot add more links because of my low score)

ASP MVC 4 Data passing

Im a new ASP MVC learner, Im working on a small pieces and getting stuck. The scenario is that user is creating new account in which accountID is automatically created by SQL. I want to pass this ID to the next step, let user input name and address. How would I pass this ID or any solution for this scenario? Think about passing data by TempData or Session but I'm not sure.
TempData will save the data until the end of your subsequent request.
There is also ViewBag/ViewData, which are really the same dictionary, are shorter lasting and they last only until the end of the current request.
Session lasts for as long as the user's session is open.
I believe TempData fits your bill, if "next step" means passing the data to a subsequent view, but if you need the data to be more durable, Session is the way to go.
I think you are approaching this incorrectly. You should have the user fill out all the information first, and then do all the registration, including creating the user and storing the data from the various steps all at the end.
If you do things the way you suggest, you will end up with partially registered users. They will create an account, and then maybe close their browser and never finish the rest. You will now have to write extra code to check all this every time they log in.
It's better to simply have your registration process do this all at once as an all or nothing process.
Just use the same process you would use for your login form. If the user is already entered in the database, you might as well treat them as a logged-in user that does not have a fully filled profile, yet.
In ASP.NET MVC, this would - in a lot of cases - be solved by setting the Forms Authentication cookie to the newly registered username
FormsAuthentication.SetAuthCookie(newUser.Logon, false);
I think that storing the user id in TempData or Session is the wrong scope for that. For all normal purposes, a user that just registered to your website can be treated as logged in after the record has been inserted in the user database.
You can try this way -
Create the user (username and password will be the values from your form):
WebSecurity.CreateUserAndAccount(username, password);
And then do this:
int userID = 0;
userID = WebSecurity.GetUserId(username);
Hope that helps.

Method security in Spring Security

I have a question regarding using Spring Security to protect against SQL injection. First of all, I know that use prepared statement can protect from any SQL injection. But In my project I want to show that use Spring Security could help to protect or mitigate against this kind of attack. what i did so far, i made connection using JDBC & Spring and I applied Spring Security and every thing is fine. My question is in my project i used two ways to protect against SQL injection. The first one is Santizing user input and the second one is using Spring Security. I could pass malicious input through Sanitizaing and I want to show that the role of spring security. for example, I pass this input:
TV' UNION SELECT credit_no From credit;--
In this case how I can tell Spring security that it doesnot give any users the credit number. By the way, I used method security level. Just I want to give me an easy way to analyze the user input to see If it has access to data which he asked such as credit.
I hope that clear
Well, your question is not 100% clear, and it may vary on your architecture, but pre post annotations can work well to grab user input.
You can create your own permission evaluator and check permission for pre authorization in your methods.
#PostFilter("hasPermission(filterObject, 'customoperation')")
public CreditCard getCreditCard(String userInput) {
//
}
and your hasPermission method (that you've read about in the link above) goes something like:
public boolean hasPermission(Authentication authentication,
Object target, Object permission) {
if ("customoperation".equals(permission)) {
//your logic here, returning true or false, filtering the object
}
return false;
}
You can also extend the expression handler to use custom functions. Check this answer.

ACL on field level in Grails

in our new software project, we have the following requirement: A webpage shall show a set of data. This data shall be editable by some users (assigned to roles, i.e. manager), and only viewable by others. The tricky part is described by an example:
A User-page consists of address data and account information. The addess data shall be editable by the user and the manager and viewable by all users, while account information shall only be viewable by the actual user and the manager.
I have read a lot of information about SpringSecurity. It provides a very good framework to gran permissions on urls and methods and even domain classes. But what I need is field level ACLs. At least, that's what I think at the moment.
So, the question is: How to solve this problem using Grails?
Thanks a lot in advance,
Regards Daniel
Spring Security (Acegi Plugin) is definitely the way to go with Grails.
There is a taglib you can use that will allow a page to be different for different roles such as the following:
<g:ifUserHasRole roles="ROLE_ADMIN">
html code for extra fields
</g:ifUserHasRole>
Me, I'd encode it on the domain class, emulating the way GORM has you annotate the domain classes (static access = [field1: "ROLE_USER", field2: "ROLE_ADMIN,ROLE_USER"] as an example). Then build a method your controller could use to redact them for a given user. That method could use the domain class's annotations to decide how to redact it. Then, metaprogram it onto each of the domain classes the way plugins do.
Similarly, write the opposite method to restrict data bindings of params into the domain class, write your own data binding utility method, then metaprogram it onto each domain class as well.
Then you can just use instance.redact(user) or instance.bindData(params, user) to do what you want, and it's practically declarative syntax.
We have a similar situation and use both the ifUserHasRole tag in the gsp to drive the appropriate presentation and the we have a filter that enforces the rules based on the action being called. For example, on user controller we would only allow the management roles to call save action, or if the user.id is the same as the session.user.id. This seemed to be the best option for our situation.
What about creating an ACL class like this:
class ACL(val entry: Entry*) {
def isAccessAllowed(subject: String, permission: String): Boolean = ...
}
class Entry(val subject: String, val permission: String*)
usage:
new ACL(
new Entry("dave", "read", "write"),
new Entry("linda", "read")
)
(This example is in Scala, because I found it more expressive in this case, but it should be easy to transfer it to Groovy.)
You would then connect an ACL object with the object to be protected.

Resources