I am trying to understand functioning of spring security filters. I am reading the documentation and currently stuck at understanding who really inject the instance of FilterChainProxy.
I tried checking for -
any auto config in spring boot if that creates this
source code of spring-security to see if there is anything like : new FilterChainProxy(..)
But no luck.
I found below in javadoc of class FilterChainProxy :
I tried checking if there is any xml config that is instantiating the class. But no luck here again.
Can anyone guide ?
As stated by javadoc, the WebSecurity is created by WebSecurityConfiguration to create the FilterChainProxy known as the Spring Security Filter Chain (springSecurityFilterChain).
In WebSecurity class an instance of FilterChainProxy is created in performBuild() method using the constructor with List<SecurityFilterChain> filterChains argument.
Related
I'm trying to use the recently released Spring Session library to do external session management in Redis. I'm using this guide. When I try to start my server, I get this error:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
I assume this is because my webapp already has code for context initialization. I would prefer to leave that code as is. Is there some way to achieve the result of that tutorial without having to do an additional context initialization? It doesn't really seem like it should be necessary if I can add the springSessionRepositoryFilter bean and corresponding filter object myself, but I don't know how the Spring Session code does that internally.
With Spring Boot application it does not need using initializer classes as spring offical reference:
http://docs.spring.io/spring-session/docs/current-SNAPSHOT/reference/html5/guides/boot.html .
Also using spring security you can check below spring tutorial:
https://github.com/spring-projects/spring-session/tree/master/samples/javaconfig/security/src/main/java/sample
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
public class Initializer extends AbstractHttpSessionApplicationInitializer {
}
If you want to configure with maven instead of gradle you can check my answer in comment.
Hope it helps!
The changes you need to make to your existing initializer should be minimal. First, it probably implements WebApplicationInitializer currently and this should be changed to extend AbstractHttpSessionApplicationInitializer. Second, in your onStartup method, add super.onStartup(servletContext) after your existing initialization code.
public class Initializer extends AbstractHttpSessionApplicationInitializer
{
#Override
public void onStartup(ServletContext servletContext) throws ServletException
{
// existing code
super.onStartup(servletContext);
}
}
I know you were not wanting to change your initializer, but this is a very minimal approach to make it work.
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!
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.
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.
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" ;)