We're using the Grails spring security plugin:
http://grails.org/plugin/spring-security-core
I simply want to change the default access decision manager from the default AffirmativeBased to UnanimousBased. I do not see it documented anywhere in the plugin manual:
http://grails-plugins.github.io/grails-spring-security-core/docs/manual/
Does anyone know if it's possible to change this?
I added one additional voter, "myVoter" which is detected and working fine.
grails.plugins.springsecurity.voterNames = [
'myVoter', 'authenticatedVoter', 'roleVoter',
]
Based on Burt Beckwith's "Hacking the Grails Spring Security Plugin" [http://www.slideshare.net/gr8conf/hacking-the-grails-spring-security-plugins], it should be possible to simply provide a different implementation of the accessDecisionManager bean. Something like this:
accessDecisionManager(org.springframework.security.access.vote.UnanimousBased)
in resources.groovy
When I tried this, I had trouble with the constructor syntax in the bean definition. The access decision manager wants a list of voters in the constructor and I couldn't quote figure out how to get my voters defined in config.groovy as parameters to the constructor. I was about to derive my own decision manager (with parameterless constructor) from UnanimousBased when I stumbled upon the source code for AuthenticatedVetoableDecisionManager in the Grails Spring Security Plugin. This class splits the voters in half... anything deriving from AuthenticatedVoter will immediately fail if any are denied (e.g. AUTHENTICATED_FULLY family), but all other voters will pass if any are granted (e.g. RoleVoter). I wanted the AuthenticatedVoter functionality for my custom voter so I simply derived from AuthenticatedVoter (making sure to override all of the interface methods so I didn't accidentally get any base class functionality) and stuck with the default decision manager.
Related
Please note: Although my specific question at hand involves the Grails Shiro plugin, I believe this to be a core Grails question at heart. And so any battle weary Grails veteran should be able to answer this, regardless of their experience with Grails Shiro.
Using the Grails Shiro plugin (via grails shiro-quick-start) produces a Shiro realm class under grails-app/realms. For instance, running:
grails shiro-quick-start --prefix=com.example.me.myapp.Mongo
...will produce:
myapp/
grails-app/
realms/
com/
me/
myapp/
MongoDbRealm.groovy
Where MongoDbRealm is the Shiro realm.
package com.example.me.myapp
class MongoDbRealm {
FizzClient fizzClient // How to inject?
BuzzClient buzzClient // How to inject?
FooFactory fooFactory // How to inject?
// lots of auth-centric, generated code here...
}
Let's pretend that MongoDbRealm is very complicated and needs to be injected with lots of complicated objects such as service clients and factories, etc. How do I properly inject MongoDbRealm?
Will #PostConstruct work here? Can I inject Grails services into it like I do with controllers? Something else?
Again, I would imagine that dependency injection works the same here (with Grails Shiro and my MongoDbRealm) as in any other class defined under grails-app. I just don't understand how grails-app/* dependency injection works.
Plugins that support defining classes under grails-app typically do so by defining a new type of artifact, and specify an ArtefactHandler implementation to manage that. The Grails ArtefactHandlerAdapter class implements that interface and provides a lot of common functionality, so that's often used, and is used in the plugin's RealmArtefactHandler class.
Dependency injection would be configured in the newInstance method. You can see where I did this for one of my plugins here. Since the Shiro plugin doesn't override that method from the base class, it looks like dependency injection isn't supported.
Note that using #PostConstruct (or implementing InitializingBean) would work if the realm classes were registered as Spring beans, but it doesn't look like that's the case in this plugin.
I try to avoid using the Holders class since in most cases it's straightforward to use DI instead of pulling in dependencies explicitly, but it looks like you will need to use that approach here, e.g. fizzClient = Holders.applicationContext.fizzClient (assuming that is registered as the "fizzClient" bean).
I am trying to access the Config of the grails application via the #Secured annotation of spring security with the aim to externalize the role name later.
Sadly, I wasn't able to get this working. Neither by trying to use deprecated ConfigurationHolder class nor getting reference to grailsApplication object.
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
#Secured([CH.config.grails.app.user])
class MyController { ...}
Config.groovy:
...
grails.app.user = "ROLE_APPNAME_USER"
...
Does anyone have an advice how to solve this?
EDIT
Came across Burt's article which was informational.
You can't - annotation element values must be compile-time constants because they're resolved by the compiler and stored as part of the class bytecode.
You may have more luck using one of the other mechanisms to specify security constraints (static rules or Requestmap instances in the database) instead of annotations.
I am using spring security annotations in my project. There are scenarios when i want to invoke security-less version of the annotated object. Spring by default creates a security-enabled proxy of the annotated object and uses it for autowiring in the code, is there any way that i can achieve this using spring ?
An obvious way to do this would be to manually create proxy classes corresponding to each class for which i want this feature have those methods annotated and the implementation of these methods just delegate it to the actual object.
As an option in a case of JDK proxies you can get actual bean at runtime:
MyBean proxy;
if(AopUtils.isJdkDynamicProxy(proxy)) {
MyBean actualInstance = (MyBean) ((Advised)proxy).getTargetSource().getTarget()
}
actualInstance.doSomethingSecured(); // no advice related to this method will be called
// so your security annotation will be ignored (transactions, cache, and everething that requires AOP too...)
But from architectural point of view approach with manual proxies looks less error phrone (except if you absolutely sure that you do not need security and all another possible aspects too).
You can improve readability using generics:
MyBean actualInstance = extractProxyTarget(proxy, proxy.getClass());
actualInstance.doSomethingSecured();
Is there a way to define access to GORM methods (e.g.: save, delete, update) with Spring Security?
I've seen ACL's plugin documentation but, although I think that the plug-in allow me to define the access, I can't see clearly how to do this.
ACL's doc: http://burtbeckwith.github.com/grails-spring-security-acl/docs/manual/guide/single.pdf
Note: The examples in the documentation define access on class instances individually. I want to define them in a class level.
not sure how to do eaxactly with grails but you should write pointcut for security on domain object
<global-method-security pre-post-annotations="enabled">
<!-- Block anything ending with the word 'Controller'-->
<protect-pointcut expression="execution(* my.pkg.*Domain.*(..))" access="NON_EXISTANT_ROLE"/>
</global-method-security>
Hi
I am new to Spring Security 3 and was trying out #PostFilter on a method declared in an Interface but the returned Collection is not getting filtered.
Here is the code:
public interface IProductService {
#PostFilter("(!filterObject.customersOnly) or (filterObject.customersOnly and hasRole('ROLE_USER'))")
Collection<Category> getCategories();
}
customerOnly is a boolean attribute in a domain object Category.
I've added the following element on xyz-security.xml:
<global-method-security pre-post-annotations="enabled" />
Could someone help me understand what am i missing?
Thanks
The typical causes for this are:
AspectJ and/or CGLIB JARs are not in your classpath.
You have the annotation on an interface OR on a class (review the Spring AOP docs to determine which is supported for which AOP implementation).
You have added the Spring Security configuration to a different ApplicationContext than where you have declared your secured beans (for example, you are trying to secure a bean in your *-servlet.xml file, when your Spring Security configuration is declared by the ContextLoaderListener).
You have removed or altered the declaration so that the annotated bean is not processed by the same ApplicationContext where Spring Security is configured.
If none of these suggestions applies, please enable DEBUG logging and watch application startup to see if the bean annotation is processed at all.
As an aside, I have had many readers report similar flavors of this problem - the source code for this sample does work, but in all cases it has been true that readers have subsequently changed one of the above 4 items, causing the sample code to "break" ;)