I am new to grails. And I have to work with session. I have seen the session documentation. But no idea where to put the code in my controller. I have a page for student creation names createStudent. Now I want that this page only be access able when the user will be in session. Now how can I do it. Should I have to set the user in a variable at the time of login. Can anyone please help me on this ?
def index() {
def user = session["user"]
if (user){
redirect(controller: 'admistratorAction', action: 'createUser')
}else{
redirect(controller: 'login', action: 'index')
}
}
You could use the session.getAttribute(key) and session.setAttribute(key, value) methods inside your controller. Alternatively, there are plugins such as the Spring Security Core Plugin that already handle this very well.
There's a good tutorial by Peter Ledbrook for the Spring Security plugin here and the plugin documentation links to at least one other tutorial.
** Edit **
As you suggested, in order to use the session directly the user would need to be set in the session at an earlier point. For example:
def setCurrentStudent() {
def aStudent = [name: "Student1"]
session["user"] = aStudent
render "Added $aStudent to the session."
}
Spring Security will do this automatically at login. Then, the current user can then be accessed at any time using the springSecurityService.
class SomeController {
def springSecurityService
def someAction = {
def user = springSecurityService.currentUser
…
}
}
Related
So the thing that I want to do is direct the login page to the admin page(e.g: "admin.gsp") if username "admin" is entered and password "pass" is entered. or direct it to the user page if username "user" and password "pass" is entered
However I do not understand how exactly controller works.
So when you redirect the page to a specific controller and specific method, how do you make it redirect it to a specific page. What code do you implement inside that method ?
to explain my question better. Below we have the code for controller User, with an if else statement depending on what the user typed in the login boxes.
package file_download
class UserController {
def index() {
//code that directs the page to username page, let's call it or user.gsp
}
def login = {
if(params.username == "admin" && params.password == "pass")
{
session.user = "admin"
redirect(controller:"admin",action:"admin")
}
else if(params.username == "user" && params.password == "pass")
{
session.user="user"
redirect(controller:"user",action:"index")
}
else
{
flash.message = "login failed"
}
redirect(controller:"user",action:"login")
}
def logout = {
session.user = null
redirect(action: 'index')
}
}
now here, we have the admin controller, with the action index, that should have a code implemented to direct the page to... admin.gsp, or admin.html, watever the admin page is called
package file_download
class AdminController {
def index() {
//code that takes us to admin page let's call it admin.gsp
}
}
How do we exactly do that ?
I need a little bit of an explanation on controllers.
Thank you. Please ask if you need more clarification on the question as I will edit it.
I think you are having wrong assumptions. In Grails (I don't know rails) when you go to the login page, let's say
/app/user/login
then, at FIRST the controller method is being called (def login()), so your logic shouldn't go there, it should actually do nothing and by convention it will end up rendering login.gsp. Next, your user fills in his username/pass and submits form, there goes the second request let's say to
/app/user/auhtenticate
and here's where your logic should go and the redirects will work as you expect
So basically - controller method is called first and (unless you specify gsp to be rendered or do a redirect) after the method is executed, the gsp view is being rendered
I know nothing of rails, however in grails what you are looking for is render.
Render:( http://grails.github.io/grails-doc/latest/ref/Controllers/render.html )
so the code would look something like this
def index() {
render view: "/directory/inside/views/admin" model: [thing1: "Thing One"]
}
I need to display/hide action buttons depending if the user can access (by role definition) the specific controller/action. I'm using Spring Security plugin.
My goal is to used the annotation #Secured("ROLE_...") for every method of each of my controller and I'm looking for a way to check, before calling the action, if the user has access to this specific action. I'm guessing there is way to check this because the annotation brings the information but I cannot find any solution.
In this example I'm trying to find the HASACCESS method:
The controller with the #Secured annotation
class MyExampleController{
#Secured("ROLE_ADMIN")
def myMethod(){ do stuff.. }
}
The HTML code to include de link
<role:link controller="myExample" action="myMethod">Action</role:link>
And my tagLib role
class RoleTagLib {
static namespace = "role"
def link = {attrs, body ->
User user = (User) springSecurityService.currentUser
if(HASACCESS(user, attrs.controller, attrs.action)){
out << g.link(attrs, body)
}
}
}
I found in this thread the "hasAccess()" method contained into the SecurityTagLib but this method is protected and even when I extend the SecurityTagLib with mine the call of this method returns me "No signature of method...". I think it uses the interceptUrlMap defined in Config.groovy and not the annotations anyway.
EDIT: I succeed to extend the security tagLib and use the "hasAccess" method but it seems that it uses only the interceptUrlMap contained in Config.groovy and doesn't care about the annotations I put in my controllers.
Use
<sec:ifAllGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">
secure stuff here
</sec:ifAllGranted>
or
<sec:ifAnyGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">
secure stuff here
</sec:ifAnyGranted>
according the Spring Security Core Grails plugin documentation.
Or simply use the Spring security core taglib with your tag library.
class RoleTagLib {
static namespace = "role"
SpringSecurityService springSecurityService
def link = { attrs, body ->
User user = (User) springSecurityService.currentUser
sec.ifAnyGranted(roles: 'ROLE_ADMIN,ROLE_SUPERVISOR'){
out << g.link(attrs, body)
}
}
}
Ok I found a solution. The method "hasAccess" in SecurityTagLib is based on grails.plugins.springsecurity.securityConfigType in Config.groovy. My initial value was SecurityConfigType.InterceptUrlMap and then I would have defined every url accessible and specify which role can access each of them manually in the grails.plugins.springsecurity.interceptUrlMap
The solution is to change this to SecurityConfigType.Annotation and modify interceptUrlMap to staticRules. Then the method "hasAccess" is based on the annotations defined in the controller and can hide properly the content with my tagLib wrapped from SecurityTagLib.
There is the code in Config.groovy
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.Annotation
grails.plugins.springsecurity.staticRules = [
... your rules ... for example:
'/**': ['ROLE_ADMIN_ACCESS']
]
The code of my tagLib
class RoleTagLib extends SecurityTagLib {
static namespace = "role"
def link = { attrs, body ->
if (hasAccess(attrs.clone(), "link")) {
out << g.link(attrs, body)
}
}
}
And I use this to show or hide any link in my .gsp files based on the #Secured annotation put for every action of every controller
<role:link controller="myController" action="myAction">
Action
</role:link>
This is for Grails 2.3
To check action access from another controller or service, do this:
#Secured(["ONE_OF_MY_ROLES"])
class SomeController {
SecurityTagLib securityTagLib = (SecurityTagLib)Holders.grailsApplication.mainContext.getBean('grails.plugins.springsecurity.SecurityTagLib')
def show() {
def access = securityTagLib.hasAccess([controller: 'product', action: 'show'], 'access')
}
}
Member have many jobs. A member can add, delete or update Jobs. Currently there are actions (add, delete or update) defined in a controller which are called through jQuery.ajax(). We are sending job id and member id to perform the operation. Member id is necessary because there is a role admin who can modify the job on behalf of members, so we need to identify the member. But sending member id is dangerous as anyone can send the request by modifying the member id.
I know, we can add constraint do restrict that only admin can modify the jobs or a member can modify only his jobs. My question is, Do I need to add these constraints in the action of the controller or Is there any Grails way to do that. I have google, the same thing is handled in Ruby and Rails by using routes. And in grails I have skim through RESTful URL mapping, which is perhaps used for this purpose.
Can anyone points me to right direction, thanks. I am using Grails 2.1.1.
You can implement some realization of AbstractPersistenceEventListenerService to not allow perform actions with entity that constains id of not logged in user. Example:
class MultiTenantPersistenceEventListenerService extends AbstractPersistenceEventListenerService {
def springSecurityService
#Override
protected AbstractPersistenceEventListener createPersistenceEventListener(Datastore datastore) {
return new MultiTenantPersistenceEventListener(datastore)
}
}
class MultiTenantPersistenceEventListener extends AbstractPersistenceEventListener {
MultiTenantPersistenceEventListener(final Datastore datastore) {
super(datastore)
}
#Override
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
def entity = event.getEntityObject() // could be your Job domain entity
def user = springSecurityService.getCurrentUser() //current logged in user
if(entity.hasProperty('userId')){ // every job belongs to User
if(entity.userId != user.id){
throw new AccessDeniedException("Acces Denied !")
}
}
}
}
I'd recomment to use grails spring-security-plugin. There is a lot of information in web about plugin and it's easy configurable. Plugin allows you to perfrom controller's action in secure way. For example:
#Secured(['ROLE_USER'])
def followAjax = { ... }
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
def personal = { ... }
For more information - plugin and spring-security with grails.
You can use Authorize attribute to authorize the user,
e.g
[CustomAuthorize(Roles=SiteRoles.Admin|SiteRoles.HelpDesk)]
public ActionResult Index()
{
return View();
}
This is a nice approach for making website secure.
go through these link, this will help you.
custom authorization with asp.net mvc
asp.net mvc authorization
I am new to grails. I have recently used session in my controller. But for only one page. Now I want to use session for a number of pages. But I have no idea how to do it. Here is my code below which works for one page. Can anyone please help me on this ?
def index() {
def user = springSecurityService.currentUser
if (user){
redirect(controller: 'admistratorAction', action: 'createUser')
}else{
redirect(controller: 'login', action: 'index')
}
}
You may be new to Grails, I hope you are not new to HttpSession. :)
Session information is scoped only to the current web application
(ServletContext), so information stored in one context will not be
directly visible in another.
As long as you are in the same ServletContext you should be able to access session variable directly. Also look at Servlet API in grails.
#Alidad- Scroll back to last question from OP.
In that case you can take advantage of grails filter to do the check before execution of each action. As dmahapatro mentioned you can use session across your app to store user object and with this filter you can do a check before any action.
Something like this can help you achieve it.:
class SecurityFilters {
def filters = {
loginCheck(controller: '*', action: '*') {
before = {
if (!session.user)) {
redirect(action: 'login')
return false
}
}
}
}
}
I'm using the layout support (sitemesh) in Grails which works fine. I'd like to adjust my layout to have it depend on whether or not a user is logged in or not.
My grails-app/views/layouts/main.gsp contains the following code:
<g:if test="${user}">
Username: ${user.username}
</g:if>
However, it appears as if the layout-GSP:s are unable to access the model and hence the user variable (I get a "No session" exception when trying). What would be the recommended way to make my layout depend on whether or not a user is logged in or not?
Thanks in advance!
I would suggest to use either the request or the session scope for that purpose. Probably the most DRY way is to populate the scope is a filter. For example in the file grails-app/conf/SecurityFilters.groovy (you'll need to create it):
class SecurityFilters {
def filters = {
populateCurrentUser(controller: '*', action: '*') {
before = {
request.user = User.get(session.userId)
}
}
}
}
The example assumes that you store the id of the current user in the session attribute "userId" and that you have a Domain class "User". Using it in the layout is as simple as this:
<g:if test="${request.user}">
Current User: ${request.user.username}
</g:if>