I'm trying to override the default permission evaluator in Spring Security 3.0, but no matter what I do, the permission elevator is ignored and the default, DenyAllPermissionEvaluator is invoked instead.
I'm using programmatic configuration, and I've tried setting the permission evaluator by overriding the configure(WebSecurity) and configure(Http) methods of the WebSecurityConfigurerAdapter class, but this doesn't help much.
What is the proper way of setting a custom permission evaluator that will actually be used by Spring Security?
Using xml conf
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
<security:expression-handler ref="methodSecurityExpressionHandler"/>
</security:global-method-security>
<bean id="methodSecurityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="defaultPermissionEvaluator"/>
</bean>
and then simply define your bean like normal :
<bean id="defaultPermissionEvaluator" class="com.your.class.implements.permissionevaluator"/>
haven't done with java conf (am I the only person still using xml conf?), but shouldn't be to hard to convert from the above. And make sure you are defining in the correct place, which in most situations is the root context, hwoever we did it in the web context, so as to secure the controllers
Related
I am using #Cacheable for caching the result of a method at Service layer in Spring 3.2. following method code is used inside service Class:
#Cacheable("questions")
public List<ABClassObject> getSecutityQuestionsList(){
List<ABClassObject> list = new ArrayList<ABClassObject>();
----------------
list = ----[DAO call]
return list;
}
xml Configuration
<cache:annotation-driven />
<!-- Generic cache manager based on the JDK ConcurrentMap -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="questions" />
</set>
</property>
</bean>
Can't use EhCache because of using jdk 1.6.
By using the above code pattern i am unable to cache the List result.DAO is called all the time when i call the above method.
So, Suggest me whats wrong with the code.
Thanks in advance.
Some things you should check:
The class of getSecutityQuestionsList method is a spring bean, i.e, you don´t use a new operator anyway.
The method getSecutityQuestionsList is called from another bean
In your xml configuration put a context:component-scan base-package="xxxxx"
Put a break point inside your method. In the stack trace you should see some spring proxy stuff. When you call this method of your service, you should actually be calling a spring proxy.
I already know how to handle internationalization in a Spring application using <spring:message code="xxx"/> in a JSP page. Now my users are allowed to change languages using simple links like
IT and EN
Now, I have to handle internationalization inside a class. This is what I did:
1) I created a text.xml file to identify where my texts are
.....
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="struttura"></property>
</bean>
......
2) I created a different properties files according to different languages
3) I use this method to get the message according to the locale
......
ApplicationContext context = new ClassPathXmlApplicationContext("text.xml");
String stringa = context.getMessage("textCode",null, locale);
.......
Everything works. But I'm sure this is not the fastest and cleanest way to do it. It looks too intricate!
Does anybody know a better way to reach my goal?
MessageResource is a Spring managed bean so you can just inject it into your controllers (or other Spring managed classes):
#Autowired
private MessageSource messageResource;
I have a spring component which was used as a flex-blazeds endpoint (using #RemotingDestination) and I now need to reuse it as a REST endpoint.
What I did was create an additional rest servlet (of type DispatcherServlet of courser) in addition to the existing blaze-ds servlet I had.
I then wanted to access the same components using REST (hence my previous question) and I found that I'm getting a 404.
My rest-servlet.xml configuration file looked something like:
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonConverter" />
</list>
</property>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
</bean>
And my ContextLoaderListener uses all my spring context files, which included the compontent-scan of those components.
Since the flex-servlet had no problem accessing these #Component beans which were scanned by the global context I assumed that the rest-servlet will also had access to them and I just need to add the annotations to the components.
The strange part was that when I explicitely added the component-scan for the package where these components reside then the rest call worked.
This meant that these component beans were being created twice, once for the global context (as it scans a config file containing this scan for the flex servlet) and one for the rest-servlet context (I verified this with a simple static counter and a lock on the class).
My question is why can't the rest-servlet see the beans the flex-servlet can?
While it's true that the servlet appcontext can access the beans from the ContextLoaderListener appcontext, those beans will not be consulted when mapping HTTP calls to controllers. All controller beans must be declared (or scanned) directly in the servlet's appcontext, else they will be ignored.
I suggest that you separate the REST entry point annotations (i.e. #RequestMapping) from your BlazeDS ones. For example, take your UserService class from your other post: create a UserController class, put the REST annotations on that, and delegate from UserController to UserService. UserController would be declared in the servlet app context, and injected with the UserService from the ContextLoaderListener context.
You need to use Spring Web context and define a DispatcherServlet, which will be a child context for the one loaded by ContextLoaderListener.
It is DistpatcherServlet that should load your rest-servlet.xml, not ContextLoaderListener. Otherwise, the guys whom you call "servlets" and who, in fact, I assume, are controllers, just won't get the requests from your client.
You can read about all this stuff here: http://static.springsource.org/spring/docs/3.1.0.RC1/spring-framework-reference/html/mvc.html
This is a standard way of doing Web-related things in Spring, and you definetely need to follow it.
It should be easy:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="myInterceptor" />
</list>
</property>
</bean>
but this way the interceptor isn't called.
By default, Spring will register a BeanNameUrlHandlerMapping, and a DefaultAnnotationHandlerMapping, without any explicit config required.
If you define your own HandlerMapping beans, then the default ones will not be registered, and you'll just get the explicitly declared ones.
So far, so good.
The problem comes when you add <mvc:annotation-driven/> to the mix. This also declares its own DefaultAnnotationHandlerMapping, which replaces the defaults. However, if you also declare your own one, then you end up with two. Since they are consulted in order of declaration, this usually means the one registered by <mvc:annotation-driven/> gets called first, and your own one gets ignored.
It would be better if the DefaultAnnotationHandlerMapping registered by <mvc:annotation-driven/> acted like the default one, i.e. if explicitly declared ones took precedence, but that's not the way they wrote it.
My current preference is to not use <mvc:annotation-driven/> at all, it's too confusing, and too unpredictable when mixed with other config options. It doesn't really do anything especially complex, it's not difficult or verbose to explicitly add the stuff that it does for you, and the end result is easier to follow.
Problem I faced: Spring MVC tag doesn't go well with custom definition of DefaultAnnotationHandlerMapping.
Why..? the reason is very well explained in the answers above.
Why i wanted to use DefaultAnnotationHandlerMapping? I want to define an interceptor for my every request. a Spring-Mobile interceptor to determine the USER AGENT..mobile or a browser?
Now Due to this clash of mvc-annotation and DefaultAnnotationHandlerMapping, I cant use DefaultAnnotationHandlerMapping anymore.
The problem comes down to how can i register my interceptors with tag.
The solution was simple...but hard to find. Posting it so it can be helpful to the other solution seekers..
Use tag and register the interceptor bean in your dispathcer-servlet.xml
example :
<mvc:interceptors>
<!-- This runs for all mappings -->
<bean class="main.com.XXX.MobileDeviceResolverHanlderInterceptor"/>
</mvc:interceptors>
The reason for this behaviour is that two beans of type org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping exist in the application context. Spring resolves the two, but asks only the first for interceptors. To fix this, the following init parameter should be set to the DispatcherServlet
<init-param>
<param-name>detectAllHandlerMappings</param-name>
<param-value>false</param-value>
</init-param>
This makes the dispatcher servlet use only the handlerMapping defined in the x-servlet.xml
It is beyond me why this is the default behaviour. I'm expecting an answer from the spring community.
In my case I can NOT get rid of <mvc:annotation-driven/> as I am using jackson for json support using annotation.
What I tried, moved my all interceptors <mvc:interceptors> in separate "xml" file (interceptor-config.xml) and imported it from my x-dispatcher-servlet.xml
<import resource="interceptor-config.xml"/>
It solve my issue and avoid default 'DefaultAnnotationHandlerMapping' beans my application context.
Rather than creating separate 'xml', you can copy/paste interceptor contents directly in 'x-dispatcher-servlet.xml'.
Following is my interceptor:
<mvc:interceptors>
<mvc:interceptor>
<!-- Intercepting specific URL -->
<mvc:mapping path="/abc/**" />
<bean id= "myInterceptor"
class="xx.xxx.xxx.MyInterceptor" />
</mvc:interceptor>
<mvc:interceptors>
In Spring MVC 3.0 you can use <mvc:interceptors> instead of manual defining the handler mapping.
In my Spring xml configuration I'm trying to get something like this to work:
<beans>
<import resource="${file.to.import}" />
<!-- Other bean definitions -->
</beans>
I want to decide which file to import based on a property in a properties file.
I know that I can use a System property, but I can't add a property to the JVM at startup.
Note: The PropertyPlaceHolderConfigurer will not work. Imports are resolved before any BeanFactoryPostProcessors are run. The import element can only resolve System.properties.
Does anyone have a simple solution to this? I don't want to start subclassing framework classes and so on...
Thanks
This is, unfortunately, a lot harder than it should be. In my application I accomplished this by doing the following:
A small, "bootstrap" context that is responsible for loading a PropertyPlaceholderConfigurer bean and another bean that is responsible for bootstrapping the application context.
The 2nd bean mentioned above takes as input the "real" spring context files to load. I have my spring context files organized so that the configurable part is well known and in the same place. For example, I might have 3 config files: one.onpremise.xml, one.hosted.xml, one.multitenant.xml. The bean programmatically loads these context files into the current application context.
This works because the context files are specified as input the the bean responsible for loading them. It won't work if you just try to do an import, as you mentioned, but this has the same effect with slightly more work. The bootstrap class looks something like this:
public class Bootstrapper implements ApplicationContextAware, InitializingBean {
private WebApplicationContext context;
private String[] configLocations;
private String[] testConfigLocations;
private boolean loadTestConfigurations;
public void setConfigLocations(final String[] configLocations) {
this.configLocations = configLocations;
}
public void setTestConfigLocations(final String[] testConfigLocations) {
this.testConfigLocations = testConfigLocations;
}
public void setLoadTestConfigurations(final boolean loadTestConfigurations) {
this.loadTestConfigurations = loadTestConfigurations;
}
#Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
context = (WebApplicationContext) applicationContext;
}
#Override
public void afterPropertiesSet() throws Exception {
String[] configsToLoad = configLocations;
if (loadTestConfigurations) {
configsToLoad = new String[configLocations.length + testConfigLocations.length];
arraycopy(configLocations, 0, configsToLoad, 0, configLocations.length);
arraycopy(testConfigLocations, 0, configsToLoad, configLocations.length, testConfigLocations.length);
}
context.setConfigLocations(configsToLoad);
context.refresh();
}
}
Basically, get the application context, set its config locations, and tell it to refresh itself. This works perfectly in my application.
Hope this helps.
For the Spring 2.5 and 3.0, I have a similar solution to louis, however I've just read about 3.1's upcoming feature: property management, which sounds great too.
There is an old issue on the Spring JIRA for adding properties placeholder support for import (SPR-1358) that was resolved as "Won't Fix", but there has since been a proposed solution using an EagerPropertyPlaceholderConfigurer.
I've been lobbying to have SPR-1358 reopened, but no response so far. Perhaps if others added their use cases to the issue comments that would help raise awareness.
Why not:
read your properties file on startup
that will determine which Spring config to load
whichever Spring config is loaded sets specific stuff, then loads a common Spring config
so you're effectively inverting your current proposed solution.
Add something similar to the following:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound"><value>true</value></property>
<property name="locations">
<list>
<value>classpath:propertyfile.properties</value>
</list>
</property>
</bean>
If what you want is to specify the imported XML file name outside applicationContext.xml so that you could replace applicationContext.xml without losing the configuration of the imported XML file path, you can just add an intermediate Spring beans XML file, say, confSelector.xml, so that applicationContext.xml imports confSelector.xml and confSelector.xml only contains an <import> element that refers to the suitable custom beans XML file.
Another means that might be of use are XML entities (defined by adding <!ENTITY ... > elements into the DTD declaration at the beginning of XML). These allow importing XML fragments from other files and provide "property placeholder"-like functionality for any XML file.
Neither of these solutions allows you to have the configuration file in Java's .properties format, though.
André Schuster's answer, which I bumped, helped me solve a very similar issue I was having in wanting to find a different expression of properties depending on whether I was running on my own host, by Jenkins on our build host or in "real" deployment. I did this:
<context:property-placeholder location="file:///etc/myplace/database.properties" />
followed later by
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>WEB-INF/classes/resources/database.properties</value>
...
</list>
</property>
</bean>
which solved my problem because on my development host, I put a link to my own copy of database.properties in /etc/myplace/database.properties, and a slightly different one on the server running Jenkins. In real deployment, no such file is found, so Spring falls back on the "real" one in resources in my class files subdirectory. If the properties in question have already been specified by the file on /etc/myplace/database.properties, then (fortunately) they aren't redefined by the local file.
Another workaround which does not rely on system properties is to load the properties of all the files using a different PropertyPlaceholderConfigurer for each file and define a different placeholderPrefix for each of them.
That placeholderprefix being configured by the initial property file.
Define the first property file: (containing either first or second)
global.properties
fileToUse=first
Define the files containing a property that can be switched depending on the property defined just above:
first.properties
aProperty=propertyContentOfFirst
second.properties
aProperty=propertyContentOfSecond
Then define the place holders for all the files:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:global.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="first{" />
<property name="locations">
<list>
<value>classpath:first.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="second{" />
<property name="locations">
<list>
<value>classpath:second.properties</value>
</list>
</property>
</bean>
Use the property defined in global to identify the resource to use from the other file:
${fileToUse}{aProperty}
If I add the JVM argument below and have the file myApplicationContext.dev.xml, spring does load
-DmyEnvironment=dev
<context:property-placeholder />
<import resource="classpath:/resources/spring/myApplicationContext.${myEnvironment}.xml"/>
I'm using Spring 3 and load a properties like that:
<context:property-placeholder location="/WEB-INF/my.properties" />