Does Grails Filter `actionExclude` work with method-based routing? - grails

I have a method-based route like:
name base: "/" {
controller="api"
action=[GET: "welcome", POST: "post"]
}
And I'd like to apply a filter to handle authorization, e.g.
class RequestFilters {
def filters = {
authorizeRequest(controller: 'api', actionExclude: 'welcome') {
before = {
log.debug("Applying authorization filter.")
}
}
}
}
But when I apply this in practice, the filter runs on all requests (even GET requests, which should use the welcome method and thus should not trigger this filter.)
When I inspect the code running the in the filter, I see that params.action is set to the Map from my routing file, rather than to "welcome". Not sure if this is related to the issue.
My current workaround (which feels very wrong) is to add the following to my filter's body:
if(params.action[request.method] == 'welcome'){
return true
}
The short question is: does Grails support this combination of method-based routing + action-name-based filtering? If so, how? If not, what are some reasonable alternatives for restructuring this logic?
Thanks!

You need to use the filter as below:
class RequestFilters {
def filters = {
authorizeRequest(controller:'api', action:'*', actionExclude:'welcome'){
before = {
log.debug("Applying authorization filter.")
return true
}
}
}
}
Apply the filter to all actions of the controller but "welcome". :)
If there is no other welcome action in the other controllers then, you would not need the controller specified in the filter as well.
authorizeRequest(action:'*', actionExclude:'welcome'){...}

Related

Accessing specific controller in grails shiro plugin

I have a grails application in which I am using shiro plugin to add security. I do not give access to any of the urls without login to any user. All goes fine. Now I want to find whether there is any way to allow access to some of the urls without login ? Some links should be working without login.
that's easy. If you've a standard shiro setup, you'll find a ShiroSecurityFilters.groovy in your projects conf-folder which looks something like this:
class SecurityFilters {
def filters = {
all(uri: "/**") {
before = {
// Ignore direct views (e.g. the default main index page).
if (!controllerName) return true
// Access control by convention.
accessControl()
}
}
}
}
just replace it with something like this:
class SecurityFilters {
def filters = {
all(uri: "/**") {
before = {
// Ignore direct views (e.g. the default main index page).
if (!controllerName) return true
// Access control by convention.
if ((controllerName+':'+actionName) in ['book:view', 'book:list']) {
return true
} else {
accessControl()
}
}
}
}
}
This will make the two actions list and view of the bookController accessible to everyone.
Hope that helps...

grails url mapping for google ajax search

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'
}
}
}
}`

Setting up the filter without controllers

I have a running tomcat at localost.
I wish to write a grails filter such that when ever user goes to localhost/filter/ intercept the call and do some processing. I created a filter which is inside conf folder
class TestFilters {
def filters = {
filter(uri:'/filter') {
before = {
}
after = {
}
afterView = {
}
}
}
}
after setting this up when I go to localhost/filter/ I get only 404 error.
Where I'm making the mistake?
Thanks in advance
If you have no FilterController the url localhost/filter has no ressource to show - so you get a 404 error. You have to adapt your UrlMappings so that localhost/filter is a valid url of application.
Add the following to UrlMappings.groovy:
"/filter" (controller: "yourController", action:"yourAction")
Now - the url localhost/filter points to yourAction in yourController and the filter should be applied.

How do I get Shiro's annotations to work in Grails?

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

Grails facebook graph plugin to check session in every controller

I'm using grails and facebook graph plugin for the user registration. However, instead of checking facebook session in every action and controller. Is there a better way to check the session before entering controller? So, I don't have to duplicate the code to check authentication.
class FacebookSecurityFilters {
def filters = {
all(controller:'*', action:'*') {
before = {
println "test"
}
after = {
}
afterView = {
}
}
}
}
I created this filter by using command grails create-filters . But it's not fired at all, I mean it didn't print "test" at all. Do I need to register the filter? I'm using Grails1.4M01
Thanks
Use a filter - it's a great way to intercept all actions, or a subset of actions based on a pattern: http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.6%20Filters

Resources