How to get current user role with spring security plugin? - grails

I am using the spring-security-core plugin in my grails app. I need to know the current user's role in a controller action. How can I retrieve that?

You can inject springSecurityService into your controller:
def springSecurityService
and then in your action, call:
def roles = springSecurityService.getPrincipal().getAuthorities()
See the docs here.

From a controller you can use two methods the plugin adds to the metaclass, getPrincipal and isLoggedIn:
def myAction = {
if (loggedIn) {
// will be a List of String
def roleNames = principal.authorities*.authority
}
}
If the action is secured you can skip the loggedIn/isLoggedIn() check.

If you simply need to check to see if a user is in a specific role then use SpringSecurityUtils.ifAllGranted which takes a single String as an argument which contains a comma-delimited list of roles. It will return true if the current user belongs to all of them. SpringSecurityUtils also has methods like ifAnyGranted, ifNotGranted, etc, so it should work for whatever it is you are trying to accomplish.

To get the user
def springSecurityService
def principal = springSecurityService.principal
String username = principal.username

SecurityContextHolder knows that:
SecurityContextHolder.getContext().getAuthentication().getAuthorities()

You can also use getAuthenticatedUser() by itself. This method is automatically injected in every controller, and thus only available from controllers. You will have to use one of the other methods if you want to access the current logged in user from anywhere else.

Related

grails and spring security acl: show only some instances of a domain class

I'm using Spring Security ACL in my Grails project to manage access into my application. I can create Admin and User to have different permissions into the application.
Now, I want that a particular user can see only some instances of a domain class object. That is:
following the example domain class object
class Patient
{
String name;
String surname;
...
}
Suppose that there are 3 created Patient objects.
I want that, if I login with
username = test1
password=test1
I can see only Patient that belongs to this User.
I think that is needed that, when I create a new Patient, it is stored that this Patient belongs to the User currently logged.
How can I do that?
EDIT:
Another problem is that, if I change the URL in the part of id to show, I can see all the Patient that are created. I want that, if I change URL manually, I see an access error. Is it possible?
EDIT 2:
How can I get the role of the user currently logged in? I've tried with the following code How to get current user role with spring security plugin? but I cannot perform the getAuthorities() because it tells me that it does not exists
I've solved EDIT2 in the following discussion grails exception: Tag [paginate] is missing required attribute [total]
I need to solve the EDIT1
thanks
If I understand you right you need to define belongsTo. This will create mapping in database from Patient to User.
Edit: to get current logged in user use
class SomeController {
def authenticateService
def list = {
def user = authenticateService.principal()
def username = user?.getUsername()
.....
.....
}
}
To map to user change logic in controller or use events to create mapping
Edit: edit create action:
class PatientController {
def authenticateService
...
def create() {
def patientInstance = new Patient(params)
patientInstance.user = authenticateService.principal()
...
[patientInstance: patientInstance]
}
...
}

Grails with Shiro - How to assign specifice permission to perticular user even he has role based permission

i installed shiro plugin in my application.i assigned one complete controller for role:'role_developer'..so if any user comes under role_developer he can access all actions of that controller..but here i want remove two actions of that controller..so please suggest me ..
here my code is:
def shiroRole = new ShiroRole()
shiroRole.name='ROLE_DEVELOPER'// create role as role developer
shiroROle.addToPermission('Person') //assigned permissions Person controller with all actionss
shiro.save()
now iam going create one user of ROLE_DEVELOPER and assigning permission some actions like person controller:create,list only
def shiroUser = new ShiroUser()
shiroUser.username='username'
shiroUser.passwordHash= new Sha256Hash("password").toHex()
shiroUser.addToRoles(ShiroRole.findByName('ROLE_DEVELOPER')
newUser.addToPermissions('person:list,create')
newUser.save()
...so here shiroUser shoud not be access all actions assigned to role_dveloper
Don't know how to do this using pure shiro API, but it can be done using grails filters
Something like this
import org.apache.shiro.SecurityUtils
import org.apache.shiro.subject.Subject
class ProjectFilters {
def filters = {
all(controller: 'Person', action: '*') {
before = {
Subject subject = SecurityUtils.getSubject()
//boolean hasRole = subject.hasRole('ROLE_DEVELOPER')
//boolean hasPermission = subject.isPermitted('Person')
if (/*your logic here*/) {
redirect(uri: '/access-denied')
return false
}
}
}
}
}
you don't need filters. :-)
I never used
shiroRole.addToPermission('Person')
but from your question I guess that's equal to
shiroRole.addToPermission('Person:*')
giving the owner of the role access to all actions of the Person controller.
It seems that you now would like to remove some of the permissions for one of the users by assigning permissions to this special user. But that's not the way it works. AFAIK, there is no way to remove permissions, and that's ok because it is more secure...
Shiro works in the following way:
Permissions like a:b give a user access to controller a and action b. A role is a collection of permissions. Permissions are additive.
So if you create a role
def shiroRole = new ShiroRole()
shiroRole.name='ROLE_USER'// create role as role developer
shiroRole.addToPermission('Person:list,show') //assigned permissions Person controller with all actionss
shiroRole.save()
and a user
def shiroUser = new ShiroUser()
shiroUser.username='username'
shiroUser.passwordHash= new Sha256Hash("password").toHex()
shiroUser.addToRoles(ShiroRole.findByName('ROLE_USER')
shiroUser.addToPermissions('person:create,save')
shiroUser.save()
this user will have access to Person:list and Person:show from the assigned role and Person:create and Person:save from his direct permissions.
As you can see, most of the time it is enough to work with roles and avoid using direct permissions.
I hope this helps...

Referring to Related Record ID In Controller On Save()

I'm still new to Grails and GORM and I got stumped on this and wasn't able to figure out what I am doing wrong. The intent is to automatically relate the record to the logged in user through the Shiro plugin for Grails.
Class User { static hasMany = [stuff: Stuff] }
Class Stuff { static belongsTo = [user:User] }
Class StuffController {
def create = {
params.put('user', User.createCriteria().get{eq('username',SecurityUtils.subject.principal)}.id)
def stuffInstance = new Stuff(params)
stuffInstance.save()
}
}
I saw in the generate-views version of the create scaffold that the relevant field was referred to as name="user.id", but neither it nor variants (such as user_id) seems to work. The query to the Users domain returns the record id necessary, and params.put in this context seems to correctly append the params object with the new value when I render to a test page (so I'm guessing it's not immutable), but this is what I get from the save():
Property [user] of class [class org.stuffing.Stuff] cannot be null
I've even tried flipping it around and going the other way, with the same result:
User.createCriteria().get{eq('username',SecurityUtils.subject.principal)}
.addToStuff(new Stuff(params))`
.save()
Anyone able to enlighten me on what I'm missing here?
Thanks!
EDIT:
Apparently I was being braindead; I was overriding the "create" method, but the default action is "save" in the _form.gsp template, so it wasn't executing that branch.
On the plus side, I did learn about dynamic finders via Burt below, so it wasn't a total wash.
Thanks for your time, guys!
Your code can be a lot cleaner - there's no reason to use createCriteria here. If you're searching by username, use a dynamic finder:
def stuffInstance = new Stuff(params)
def user = User.findByUsername(SecurityUtils.subject.principal)
stuffInstance.user = user
if (!stuffInstance.save()) {
// inspect stuffInstance.errors
}

Grails - passing domain classes between controllers

In my Grails application, I have created a User class. In one controller, I query the database to confirm that the information a user has given is valid. Then, I would like to pass that User object to another controller to do some more processing on it. Is this possible? Thanks!
For your question on passing objects between controllers, if you are using a redirect or a forward you can add objects in the param map:
redirect(action: "actionName", user: userInstance)
or
forward(action: "actionName", user: userInstance)
Another solution would be to store the user in the flash object (a temporary storage map cleared after the next request) or session:
flash.user = userInstance
or
session.user = userInstance
But in your case, as stated by tim_yates, you should create a service to handle the User entity.
To do so execute the command:
create-service com.package.user
Then add all the processing you are doing on a User in the newly created class and inject the User service in your controller like this:
def controller{
def userService
def action(){
userService.validate(...)
}
}
Essentaily what #tim_yates was getting at was the logic for all of your controllers should be in services. Then any action in any controller can execute that logic without redirecting/forwarding a request. This also is the way it should be due to the transactional nature of services.

Securing Controller Actions by User in Grails

I am using the Grails security plugin on a project. I am using the annotations on controller actions to restrict access to certain classes of users such as 'ROLE_ADMIN' or 'ROLE_USER'.
(using this as the basis for what I am doing: http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/5%20Configuring%20Request%20Mappings%20to%20Secure%20URLs.html#5.1%20Defining%20Secured%20Annotations)
My question is, how do I restrict an action so a user can only see information about themselves. For instance, lets say I have a user with id = 1. If I have an action that shows information about the user at:
mySite/User/Show/1
how do I prevent that same user with id=1 from being able to access
mySite/User/Show/2
? Is there a simple way to do this?
You can also use Grails controller interceptor if you want to apply same logic to multiple actions
class SomeController {
def beforeInterceptor = [action: this.&checkUser ]
def springSecurityService
def checkUser() {
User user = User.get(params)
User logged = User.get(springSecurityService.principal.id)
if (user.id != logged.id) {
{
redirect(action: "accessDenied", controller='access' id: params.long("id")) //re-direct accessDenied page
return false
}
return true;
}
}
Class AccessController{
def accessDenied= {
render(view: "accessDenied")
}
}
What will be the problenm with the following?:
class SomeController {
springSecurityService
// other stuf ...
def show () {
User user = User.get(params)
User logged = User.get(springSecurityService.principal.id)
if (user.id != logged.id) {
flash.message = "You can't see the profile of other users"
redirect action:"list" // You can redirect to other controller/action
return //Since grails 2 this is needed
}
// Logic for display your user
}
// other stuf ...
}
what you are asking is part of your business rules. So you are supposed to take care of these scenarios in your code rather than looking out for some plugin or helper code.
What you can do for this is, make sure id of the user accessing the user details is same as id of the user whose details are being questioned.
You can also make this check at object level but that will mean an extra query to database to fetch the user details.
Hope this helps.
I have to agree that you are trying to implement a business rule with a security aspect. If a user created some kind of document, you would not use authorization to select what is visible on their profile page, would you?
You have to draw a line on where the authorization aspect reaches and where business rules start.
In my experience, to avoid blurring the lines, i always use authorization roles as types of users associated to a set of functionality. A specific user type can have access to a series of stories, or use cases. These use cases are constrained to specific roles.
If you start asking questions about data visibility (what is hidden on a page, depending on whatever business factor), then you should stay clear of your security framework
I would disagree that you need to redefine your business logic vs security logic. It is a common use case and authorization should cover it. This is why Grails has filters. Use an authorization filter to add functionality like this:
class AuthorizationFilters {
def filters = {
userCheck(controller: 'user', action: '*') {
before = {
// Check current user id is param.id here
}
}
}
}
Thus your security logic is outside your controller. You could add other controllers if they pass in a user id or even other methods that check if a domain class is owned by the current user here.

Resources