Secured annotations in spring security - spring

I am trying to configure security annotations in spring security. But I have a question about this -
....
<security:http auto-config="true" use-expressions="true">
....
and when I use
#Secured("CUSTOM_ACCESS")
public String query();
it doesn't work. But I use
#PreAuthorize("hasRole('CUSTOM_ACCESS')")
public String query();
it works correctly and applies relevant Role. Does this mean #Secured annotations doesn't work with #PreAuthorize?
I also tried adding
<security:global-method-security secured-annotations="enabled" />
But it doesn't help.
<security:global-method-security pre-post-annotations="enabled" />
The above config works fine. Any ideas?

First off, the use-expressions setting in your <http> element has no effect on method security annotations. Those are enabled using global-method-security.
Using
<security:global-method-security pre-post-annotations="enabled" />
will enable PreAuthorize and its related annotations. The reason the secured annotation isn't working when you enable that is because there is no voter which knows what CUSTOM_ACCESS means. In its default setup Spring Security's RoleVoter only consumes attributes which start with the prefix ROLE_. See this FAQ for more information.
Voters can be used for things other than checking for simple roles, so they typically need some way of determining which of the attributes configured for a method apply to them. The expression-based annotations operate differently from the standard voters. The hasRole expression just looks for a named authority which is assigned to the user.
So if you created an AccessDecisionManager for method security, with an AccessDecisionVoter which consumes your CUSTOM_ACCESS attribute then the #Secured annotation would have an effect. However since you have it working with PostAuthorize already you may just want to stick with that.

Related

Register Spring filter from BeanDefinitionParser

I am creating a custom namespace for use in the Spring XML configuration. I already implemented a NamespaceHandler and BeanDefinitionParser. So, now I can just put <myns:some-awesome-feature /> into my Spring configuration and it creates the required beans automatically.
In addition to creating some normal Spring beans I would also like to have this annotation register a OncePerRequestFilter to extract some information off of a request for my code to be able to utilize. Is there a way to register a filter programmatically using the two classes I have available when implementing a custom XML tag?
It is not possible without touching web.xml or WebApplicationInitializer, respectively.
But you can create an extendable solution that allows modifications in future without hassle.
Spring Security's <http pattern='...' security="..."/> automatically creates and registers a series of chained filter beans for you. All you have to do is to
register DelegatingFilterProxy in you web.xml and reference springSecurityFilterChain.
You can create a similar solution where you are defining e.g. <myns:awesome-http pattern='...' /> which instantiates OncePerRequestFilter. In web.xml you are declaring a DelegatingFilterProxy which references your awesomeFilterChain. In a future version you can add more filter to your chain without touching the configuration.
I have never implemented such a feature but I'm quite confident that it is possible.
As a starting point take a look at the source of HttpConfigurationBuilder and HttpSecurityBeanDefinitionParser to see how Spring Security implemented <http .../>.

How do I add custom interceptors to my annotation scanned spring-ws endpoint

I am using Spring-ws 2.1.4.RELEASE and Spring 3.2.8.RELEASE.
I am trying to add an interceptor to my endpoint but so far no luck even though I think my setup is very basic.
In my Spring-ws XML I have:
<sws:interceptors>
<bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor"/>
</sws:interceptors>
<sws:annotation-driven/>
<context:component-scan base-package="package.with.my.endpoints" />
<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
<property name="payloadCaching" value="true"/>
</bean>
In my Endpoint annotated bean I use the Spring-ws #Action annotation for ws addressing mapping:
#Endpoint("MedicineCardIdwsEndpoint")
public class MedicineCardIdws {
#Action("http://someuriandversion#GetMedicineCardIdws")
#ResponsePayload
public String getMedicineCard(#RequestPayload Element payload, SoapMessage soapMessage) {
return "";
}
However nothing is logged by the interceptor when I send a request for my endpoint. At first I thought I had configured log4j wrongly. However, if I create a breakpoint in the first line of org.springframework.ws.server.endpoint.AbstractLoggingInterceptor#handleRequest the breakpoint is never triggered.
Then I put a breakpoint inside org.springframework.ws.soap.server.SoapMessageDispatcher#headerUnderstood I can see that the only interceptor that is registered for my Endpoint is the org.springframework.ws.soap.addressing.server.AddressingEndpointInterceptor which got added because of the Action annotation.
I thought that any global interceptors in the XML configuration would end up being added to the interceptor chain for all endpoints? However it seems this is not the case. It is not just the logging interceptor, even custom interceptors are not added. So I must be doing something wrong.
I am fairly new at using Spring-ws - did I miss something in my config, or is there an annotation I need to add in order to add interceptors for annotation scanned endpoints?
Is there another way I can add interceptors to my interceptor chain when using component scanning and annotations for Spring-ws or do I need to configure all of it in XML in order to be certain that my interceptors are added to my endpoints?
I found that if I use #SoapAction annotation instead of the WS-Addressing #Action (bot from Spring-ws packages) my custom interceptors from the XML config will get added to the endpoint.
I also found this thread in the Spring forums suggesting a workaround if #SoapAction is not an option: http://forum.spring.io/forum/spring-projects/web-services/100060-interceptors-not-working-for-ws-addressing-endpoint-action

LocaleResolver in filter null yet shows it has been autowired! Spring MVC 3.1.1/Spring Security 3.1.0

I am using Spring Security 3.1.0 and Spring MVC 3.1.1.
I would like to be able to change the locale based on URL i.e.:
http://localhost:8080/abc?lang=fr
Now, this works under "normal" circumstances, i.e. going from one page to another page HOWEVER, in my application, if I go from a non-secure page to a secure page, it first hit's my login page, courtesy of Spring Security BEFORE it hits the page I want.
This is normal Spring Security behaviour (to intercept a secure resource) so there are no problems with this behavuour.
The problem is rather that the locale does not change when I arrive at the secured page! It stays as the default locale. i..e lang=fr is not parsed out.
I have played with defining the locale related beans inside dispatcher-servlet.xml AND outside, in an app-context file to do the following:
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang" />
</mvc:interceptors>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" p:defaultLocale="en" />
I have also tried to split up the above 2 beans, having just localResolver in the app-context config.
I have done TONS of research on this and basically, I understand I need to change the locale manually.
Even the Spring Docs for Spring Security 3.1.0 say that you need your own "filter" or you can use RequestContextFilter. RequestContextFilter, however does not parse out the locale param in the query String.
Spring Security relies on Spring's localization support in order to actually lookup
the appropriate message. In order for this to work, you have to make sure that the
locale from the incoming request is stored in Spring's
org.springframework.context.i18n.LocaleContextHolder. Spring MVC's DispatcherServlet
does this for your application automatically, but since Spring Security's filters are
invoked before this, the LocaleContextHolder needs to be set up to contain the correct
Locale before the filters are called. You can either do this in a filter yourself
(which must come before the Spring Security filters in web.xml) or you can use
Spring's RequestContextFilter.
I would like to intercept the request BEFORE it hits the Controller and so, I have written my own filter.
My solution, based on what others have done as well, is to autowire the LocaleResolver. When tomcat fires up, it shows in my logs that "localeResolver" has been autowired (otherwise the app would fail right there) HOWEVER at run time, localeResolver is NULL.
Again, there have been posts that say to define LocaleResolver in the application-context...I have done so but I still end up getting a null LocaleResolver when a request happens.
Any ideas?? Much appreciated.
p.s. the filter I have defined comes before the Spring Security filters. I can debug it, it hits it first but then it dies because of the NPE on LocaleResolver.
Appreciate this, thanks.
Did you define the filter in web.xml? If so, then the filter class is not instantiated by Spring, it is instantiated by the servlet container. Spring cannot autowire what it does not know about.
The general solution here is to declare the <filter-class> in web.xml as org.springframework.web.filter.DelegatingFilterProxy and point the targetBeanName at a bean in your context, such as:
<filter>
<filter-name>My Locale Filter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>myLocaleFilter</param-value>
</init-param>
</filter>
And in your Spring context, <bean id="myLocaleFilter"> should point at your Filter class.
You might also find it convenient for your custom Filter class to extend GenericFilterBean rather than implementing the Filter interface directly.

Security access audit

I have the following spring security configuration:
<security:http>
......
<security:intercept-url pattern="/auth/**" access="ROLE_ADMIN"/>
.........
</security:http>
I would like to log every case when "ROLE_ADMIN" user hits any of "/auth/**" URL pattern.
Can I put some kind of interceptor on this pattern?
I had to do the same thing. Use an #Aspect which fires for every execution of a handler method in your /auth/ controller. Annotate the class as a #Component so its a Spring bean, add the AspectJ #Aspect annotation, and you can then inspect the JoinPoint for whatever the user is doing - method signature, objects, etc. Write whatever you find to an audit table.
See http://static.springsource.org/spring/docs/current/reference/aop.html for full details. I would think a #Before or #After would work for your purposes.

Spring annotations configuration looks like overhead

I just faced,that in order to use specific annotations for Spring Security, I should explicitely allow them in my config(applicationContext.xml)
Example:
<sec:global-method-security secured-annotations="enabled" />
<sec:global-method-security jsr250-annotations="enabled" />
...
What advantages do you see in approach of explicitely declare what annotations are allowed in our frameworked application?
Looks like overconfiguration,isn't it?
One possible benefit is that it allows Spring Security to throw an exception when desired annotations are not present in the classpath (though it's mostly about JSR-250 annotations, since other annotations are parts of Spring Security itself).
Otherwise Spring Security would have to silently ignore absence of annotations, that may lead to surprising behaviour.

Resources