I have successfully set up my Grails application to authenticate the user.
I map controller method arguments using URL params, in my UrlMappings.groovy:
"/$source/owner/$ownerId/show"(controller:"myController", action: "show", method: "GET")
How do I get the values of $source and $ownerId in my #Secured closure?
My controller method looks like this:
#Secured(closure = {
//null
def testSource = params.source
//also null
def testOwnerId = params.ownerId
//null
def owner = request.ownerId
//null
def owner2 = request.getParameter('ownerId')
//contains only query string params
def grailsParams = request['org.codehaus.groovy.grails.WEB_REQUEST']?.params
return true
})
def show(String source, String ownerId) {
...
}
How do I get these values? What am I doing wrong, here?
I thought that this post would provide a solution, but the answer given there didn't work for me:
Is it possible to hack the spring-security-core plugin #Secured annotation to be able to reference request params given to a controller?
I am using the following grails and plugin versions:
grails 2.5.1
compile ":spring-security-core:2.0-RC5"
compile ":spring-security-rest:1.5.3", {
excludes 'com.fasterxml.jackson.core:jackson-databind:'
}
Brief :
Use request.getParameter
Details :
In 2.0 you can use a closure as the annotation's check; there's a brief writeup and example in the docs: https://grails-plugins.github.io/grails-spring-security-core/v2/guide/newInV2.html
You'd express your example as this:
#Secured(closure={
request.getParameter('ownerId') >=123 //this is example
})
Return true to allow access, false to deny access.
Related
I am new to grails and I am trying to override the redirect method in groovy controller. I refereed this Override Grails redirect method. But I do not understand how do I access and pass the http request params to the redirect override in BootStrap.groovy.
redirect(action: "logout", params: [lang: params.lang])
If you implement a wrapper via metaClass on a controller (just like mentioned in your linked question), you can simply access the "active" controller object via "delegate" in your implementation closure:
def ctx = servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
def app = ctx.getBean("grailsApplication")
app.controllerClasses.each() { controllerClass ->
def oldRedirect = controllerClass.metaClass.pickMethod("redirect", [Map] as Class[])
controllerClass.metaClass.redirect = { Map args ->
// delegate is the instance of <controllerClass> where "redirect" just gets executed.
// the current http request can be accessed via a getter on controller classes
println delegate.getRequest()
oldRedirect.invoke delegate, args
}
}
alternatively, you could use the RequestContextHolder to obtain the current requestAttributes and extract the request from there (see org.codehaus.groovy.grails.plugins.web.api.CommonWebApi.java in Grails 2 or grails.web.api.ServletAttributes.groovy in Grails 3)
In a new project based on grails 2.4.4 I am using filter schema with invert option. Few controllers and some actions from another controllers are excluded in filters by inverting the rule.
Filter will not be applied to Login, ForgotPassword ans ServerError Controllers and saveUser, verifyRegistration actions from different user controller. This filter schema doesn't work as expected.
When I am calling login api inside login controller, filter is getting executed and throws exception.
package com.project.filters
import grails.converters.JSON
class MyProjectAuthorizationFilters {
def userService
def grailsApplication
def filters = {
checkXAuthToken(controller:'login|forgotPassword|serverError', action:'saveUser|verifyRegistration', invert: true) {
before = {
try{
String tokenValue = request.getHeader('X-Auth-Token')
if(tokenValue == null && tokenValue == ""){
throw new MyCustomException(401, "Please provide X-Auth-Token in Header")
}
userService.getUserByAuthToken(tokenValue)
}catch (MyCustomException error) {
error.stackTrace = ""
response.setStatus(error.status)
render error as JSON
return false
}
}
}
}
}
I know we can also use controllerExclude, actionExclude, but did not know why this is breaking?
EDIT
I even tried using controllerExclude and actionExclude but it doesn't work as expected. Is this a weired behaviour or I am doing something wrong. Posting whole filter class code.
Thanks.
Basically I am using the code below for debugging. It renders null and I cannot figure out the
reason. And by the way the else statement will always be executed at this point. At first I
didnt have the save method but I then thought it might fix my issue. May is have to do with
the scope of my domains? As of now I have them set to session scope:
class Info {
static scope = "session"
String name
String smokingStatus
String[] symptom
static constraints = {
}
}
else{//query did not find patient with that id
def patInfo = new Info()
patInfo.name = "Dennis"
patInfo.smokingStatus = "Former Smoker"
patInfo.symptom = ["Cough"]
patInfo.save()
redirect(action:"display", params: [patInfo:patInfo])
//redirect(action:"login")
//return to login action and
}
}
}
def display(){
render params.name
}
Thanks for any help its much appreciated.
You are assign the value of patInfo to variable name patInfo so in the display action you must use:
render params.patInfo
By example if you will use the following:
redirect(action:"display", params: [duck:patInfo])
You must use:
render params.duck
This is probably a very simple problem but for the life of me I can't get it to work.
I need to redirect google requests for ajax generated code to return a html template for indexing
I have the following in my urlmappings.conf
"/?_escaped_fragment_=$id"(controller:"google",action:"getOfferDetails")
However if I enter mysite?_escaped_fragment_=200 in the browser the controller is not called
If however I enter mysite_escaped_fragment=200 the controller is called and the action executed.
Any suggestions would be greatly appreciated.
Thanks
Ash
You can not use '?' char in the route matching i.e. it will be ignored.
Use this filter instead (put this class in the config folder w/ fileName CrawlerFilters.groovy):
class CrawlerFilters {
def filters = {
google(controller: '*', action: '*') {
before = {
boolean isCrawler = webRequest.params._escaped_fragment_ != null
if (isCrawler && !request._alreadyForwarded) {
request._alreadyForwarded = true
forward controller: 'google', action: 'getOfferDetails'
}
}
}
}`
I'm trying to apply annotation-based security to my Grails app.
Peter says here that we should be using Shiro's annotations instead of the quasi-deprecated grails-shiro plugin annotations.
How does one get that working?
I'm finding the grails-shiro plugin strays from how Shiro does things, what with the Realm-converting and all. Has anyone tried implementing Shiro directly rather than using the grails plugin? Any success?
Thanks,
Graham.
G'day I have taken over the Grails-Shiro plugin project. I'm currently re-writing the functional tests and can confirm that the shiro annotations do work, with a couple of caveats:
You can use them in controllers on method actions in grails 2.x
You can use them on Service methods
They don't currently work on service classes (I'm investigating this)
e.g. this works on a service
class SecuredMethodsService {
def methodOne() {
return 'one'
}
#RequiresGuest
def methodTwo() {
return 'two'
}
#RequiresUser
def methodThree() {
return 'three'
}
#RequiresAuthentication
def methodFour() {
return 'four'
}
#RequiresRoles('User')
def methodFive() {
return 'five'
}
#RequiresPermissions("book:view")
def methodSix() {
return 'six'
}
}
or in a controller on an action method like this:
#RequiresAuthentication
def unrestricted() {
render(view: 'simple', model: [msg: "secure action"])
}
When using annotations you may need to add an "afterView" filter to catch the AuthorizationException thrown by the annotation e.g.
class ShiroSecurityFilters {
def filters = {
all(uri: "/**") {
before = {
// Ignore direct views (e.g. the default main index page).
if (!controllerName) return true
// Access control by convention.
accessControl()
}
afterView = { e ->
while (e && !(e instanceof AuthorizationException)) {
e = e.cause
}
if (e instanceof AuthorizationException) {
if (e instanceof UnauthenticatedException) {
// User is not authenticated, so redirect to the login page.
flash.message = "You need to be logged in to continue."
redirect(
controller: 'auth',
action: 'login',
params: [targetUri: request.forwardURI - request.contextPath])
} else {
redirect(controller: 'auth', action: 'unauthorized')
}
}
}
}
}
}
I hope that helps. A new version of the plugin should be released RSN.
Cheers,
Peter.
Since nobody is anwering...
I don't know how you get the annotations to work, but I've used shiro in several Grails projects and didn't miss them... So why do you need them?
When you need to permission explicit roles, you can just create some ShiroRoles and assign star-permissions to them: 'book:*' allows a role to execute all actions on the book controller. 'book:list,show' allows a role to only list or show books.
When you need implicit permissions, use a filter. So if you want to give someone access if she is (for instance) the boss of someone, just fetch the object on which you want to decide in a filter and make a decision.
When you need switches in you gsp-code (e.g. show this only if it's an admin), use the shiro tags. Just unzip the shiro plugin and look for the taglibrary. It is well documented.
HTH