How do I access UrlMapping variables in grails from a filter? - grails

I'm using Grails 2.1.5 and the Spring Security Core plugin.
I've overridden the WebSecurityExpressionRoot to add 2 signatures of a hasPermission method to the web expression paradigm.
This method delegates to classes by name in the applicationContext calling them with the request as an argument and an arbitrary string to provide further details if any are ever required.
In my delegate class I need to be able to access the parameters to assess whether or not the user may access the requested resource and this is fine but the request does not yet contain the variables defined from the UrlMappings.
I have tried acquiring the grailsUrlMappingsHolder from the applicationContext but when I call it's match method with a valid uri I get nothing.
I'm running out of time and may have to parse the request.getRequestURI() myself to try to infer the id if no request parameters are valid but this will not get urls mapped where the id is not last.
I really hate to re-invent the wheel here and I hate to miss out on using the UrlMappings to their fullest potential but the variables they define (in my circumstance) aren't available until I'm in the controller.

Take a look at what I do in AnnotationFilterInvocationDefinition - there's a bit of setup that you need to do: https://github.com/grails-plugins/grails-spring-security-core/blob/master/src/java/grails/plugin/springsecurity/web/access/intercept/AnnotationFilterInvocationDefinition.java

Related

Typhoon: Injecting run-time arguments into a singleton

I'm trying to figure out how to inject run-time arguments into a singleton when it is created, and then have those arguments just be remembered from then on. I'm not sure if the interface for run-time arguments can support this, though. Say, for example, I have a Client object that requires a token, and has the following initializer:
+ (instancetype)initWithToken:(NSString *)token;
The token is obtained at runtime from the server and is different for every user, so I can't simply put the NSString in the definition. So I create the following method on my Typhoon assembly:
- (Client *)clientWithToken:(NSString *)token;
However, in the future (when I'm injecting this client into other classes), I won't have the token on hand to call this method with. So I would like to just be able to inject [self client], for example. Since the client is a singleton and has already been created, the token isn't necessary, anyway.
However, I can't seem to find a way to do this. Obviously, defining a separate method called client would just return a different client. Can I just call clientWithToken:nil and the argument will be ignored if the client already exists? Perhaps traversing the assembly's singletons array would work, but that is obviously very inelegant.
I have considered injecting by type (so I don't need a method to call), but I have multiple different clients of the same type, so I need to be explicit about which client to inject. Of course, there is also the option of removing this parameter from the initializer, and instead setting it as a property from outside the assembly; however this pattern is used throughout our application, so I would like to avoid rewriting that much code.
Thank you.
Reviewing the Typhoon User Guide's 'When to Use Runtime Arguments' shows that this scenario isn't really a good match. Runtime arguments are great when we have a top-level component that mixes some static dependencies with information that is known later - thus avoiding the creation of a custom 'factory' class. Its not possible to use them in the way described.
Instead consider the following suggestions:
Inject a shared context class
Create a mutable Session model object and register it with Typhoon. Update the state on this model when you have a token. Inject this into the clients, which will use this session information when making connections.
Aspect Hook
Hook your clients so that before a method is invoked the token information is available. This could be done by:
Using an Aspects library like this one.
Define a Protocol for the clients and wrap the base implementation in one that is security aware.

Grails Spring Security Expression - How to access Method parameter

Using the Spring Security Plugin for Grails:
Version: 2.0-RC2
For my controllers I am using the #Secured annotation.
Is there a way to access the method parameter from the spring security expression.#paramName does not work for me.
#Secured(['ROLE_ADMIN',"hasRole('ROLE_USER') && #permissionService.updateAllowed( #myInstance )"])
def update(Bug myInstance) {
The problem: myInstance is null!
Software I am using:
Grails: 2.4.3
Intellij 14
JDK 8
I didn't notice that you were doing this in a controller - there's no support for method args in annotated controllers. The reason for this is that in traditional Spring Security, the annotation is applied to Spring Beans and the bean becomes proxied, and the proxy does the security checks before calling the method and only calls the real method if the checks pass. That works well with Spring MVC controllers because they're regular Java classes, and also in Grails services because there isn't much added to services by Grails - they're really just regular Groovy classes that are auto-registered as Spring Beans, and by default are made transactional.
But controllers are weird. There is actually one SpringMVC controller in any Grails app, and it's internally created and used by Grails. It interacts with the rest of SpringMVC, and delegates to the controller that best matches the url mappings rule for the current request to do its work, and it uses that to create the ModelAndView that Spring expects. Additionally, to support databinding, there's an AST transform that runs on your code during compilation which creates a no-arg method for each method with args, and that is what is called from the Grails internal request handling code. It does databinding and type conversions, and calls the "real" method to handle the request.
The support in Spring Security for working with method args depends on debug information being available in the compiled code, and usually this is not available because it's rarely needed - javac connects everything for us at compile time and getting the value of a method arg from outside of the method isn't often needed. Grails does keep that debug info - that's why this works in a service - but it looks like the AST isn't. It might be possible to get that working, but I have no idea if it is or what would be involved, and to be honest it would likely be a lot of work for a feature that wouldn't be used a lot.
But you can rework the check to pass the params to the service and let it lookup the Bug instance and then do its check. You can access the params from the service, so there's no need to pass anything as args:
import org.springframework.web.context.request.RequestContextHolder
...
def params = RequestContextHolder.requestAttributes.params
I've managed to get a workaround for the problem described in the comments to the accepted answer. Use #this in SpEL expression:
#Secured('#securityService.userCanEditOffer(#this)')
def edit(int id) {..}
Then create such methods in your service:
def userCanEditOffer(WebSecurityExpressionRoot webSecurityExpressionRoot) {
UrlMappingInfo urlMappingInfo = Holders.applicationContext.grailsUrlMappingsHolder.match(webSecurityExpressionRoot.request.forwardURI.substring(webSecurityExpressionRoot.request.contextPath.length()))
userCanEditOffer(Integer.valueOf(urlMappingInfo.params.id))
}
#Transactional(readOnly = true)
def userCanEditOffer(Integer id) { .. }
Inside ulrMappingInfo.params you'll have id, action and controller!

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 Grails 2.3.3 and spring-security-core:2.0-RC4 plugin.
I am trying to protect a controller action by securing it depending on the result of a method call from a service that takes a parameter. This parameter should be something inside the request parameters.
I'd like to be able to do the following:
#Secured("#mySecurityService.myCustomCheck(params.id)")
def myAction(){
//do some things
}
I managed to be able to do the following:
#Secured("#mySecurityService.myCustomCheck()")
but now I have no idea how to access the request parameters that are sent to the controller.
Is it even architecturally possible to reference params variables inside the #Secured notation?
PS: I know you'll ask me to use spring-security-acl plugin. My problem is that it also adds a bunch of other things that I don't think I require.
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={
ctx.mySecurityService.myCustomCheck(
request.getParameter('id'))
})
Return true to allow access.
Note that the ApplicationContext is available as the ctx variable, and the request as request; this is in addition to the other variables and methods that are available when using SpEL (see the Spring Security docs for details). params isn't available, but you can access values using request.getParameter

Finding target of LinFu proxy object

This is pretty much a duplicate question but instead of using Castle Dynamic Proxy I'm using LinFu Getting underlying type of a proxy object
I'm using automapper to create proxies of interfaces that I'm sending to my viewmodel in Asp.net MVC. My problem is from what I can tell that MVC's default MetadataProvider find the properties and metadata by calling .GetType() on the model.
So what happens is EditorFor() and DisplayFor() templates don't generate any fields. What I need to do is find the proxy target type and then generate my templates. I know I can just parse the name and use GetType( "thename" ) but was wondering if there was an easy way.
LinFu.DynamicProxy doesn't directly expose the underlying object of a proxy. It simply redirects each method call to an IInterceptor implementation instance. In order to access the underlying object, you'll have to figure out whether or not the current interceptor instance actually has a target class instance, or not.
If you're working with AutoMapper, AFAIK, they use LinFu.DynamicObject to do a lot of the duck taping, and calling GetType() on a dynamic type generated by LinFu.DynamicObject won't even get you the actual type in your domain model--it will just get you an object that has been literally duck-taped together by LinFu itself.
get latest AutoMapper - it uses Castle Dynamic Proxy, and you already know how to get this from there :)

OpenRasta - Pass parameters to custom Codec

I've created a new custom JSON codec for OpenRasta which works fine.
I need to pass arguments to the codec's write method when the handler is executed but cannot find any documentation on how to do it.
I notice in the implemented WriteTo method, there is a string[] codecParameters parameter, however no idea how to pass them in.
Anyone come accross this problem before? Thanks
the codec parameters are per-request. They're intended to be used together with (for example) the PathSegmentAsParameterUriDecorator.
For example, if you enable that decorator, the path /resource;segment will be treated as /resource by openrasta, and a parameter will be created with the "segment" value, and passed to the codec.
If you wish to pass information to the codec from the handler, there's nothing there, as architecturally it goes against the design of OpenRasta, which specifically prevents handlers and codecs from talking to each others.
If you wish to pass configuration data to your codec, you use the Configuration property from the ICodec interface, which will be filled with whatever object you have provided at configuration time.
You provide the configuration object either through the paramter in the .TranscodedBy(object configuration) method, or if you do custom registration using the configuration metamodel, bu adding the configuration to your Configuration property on CodecModel (which incidently is used in the ResourceModel object created by the fluent API).
Do you have a specific scenario I can help with?

Resources