WebXmlMappableAttributesRetriever webXmlInputStream missing in spring security 4.2.0 - java

In Spring Security 2.0.7, I am configure the WebXmlMappableAttributesRetriever as follow:
<bean id="mappableRolesRetriever"
class="org.springframework.security.ui.preauth.j2ee.WebXmlMappableAttributesRetriever">
<property name="webXmlInputStream">
<bean factory-bean="webXmlResource" factory-method="getInputStream"/>
</property>
</bean>
<bean id="webXmlResource" class="org.springframework.web.context.support.ServletContextResource">
<constructor-arg ref="servletContext"/>
<constructor-arg value="/WEB-INF/web.xml"/>
</bean>
<bean id="servletContext" class="org.springframework.web.context.support.ServletContextFactoryBean"/>
However, when come to spring security 4.2.0, the webXmlInputStream property no longer exist in WebXmlMappableAttributesRetriever. I go to check the source code in WebXmlMappableAttributesRetriever, the afterPropertiesSet() method and I saw it doing something like retrieving data from /WEB-INF/web.xml like what I set in Spring security 2.
Resource webXml = resourceLoader.getResource("/WEB-INF/web.xml");
Document doc = getDocument(webXml.getInputStream());
Does this means that I no longer need to do this configuration in Spring security 4?

Related

Adding SocialAuthenticationFilter using SpringSocialConfigurer via XML for enabling sign in through social providers

I am trying to use spring social 1.1.4 for implementing social provider sign-ins.
In the docs, here we can configure SocialAuthenticationFilter through SpringSocialConfigurer. The example here is for Java Configuration.
However, due to some restriction of using existing framework which is based on XML config, I need to implement the above using XML configuration only.
How can I inject this SpringSocialConfigurer in spring security config xml. I mean, should I use
<sec:custom-filter ...>
or
<sec:http ...>
or anything else ?
You can add it to security configuration:
<!-- Adds social authentication filter to the Spring Security filter chain. -->
<security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER"/>
And add bean:
<bean id="socialAuthenticationFilter" class="org.springframework.social.security.SocialAuthenticationFilter">
<constructor-arg index="0" ref="authenticationManager"/>
<constructor-arg index="1" ref="userIdSource"/>
<constructor-arg index="2" ref="usersConnectionRepository"/>
<constructor-arg index="3" ref="connectionFactoryLocator"/>
</bean>

Switch LDAP connection at runtime in Spring

I am new to spring. Admins of my spring based web app want to configure settings from the web interface, so users can authenticate against LDAP server with their company username and password.
Change in LDAP settings should be possible without restarting the application. This might happen during a 'migration' or whatever reason. I have a couple beans, which need to be refreshed after the admin saves new settings for the LDAP server:
<bean id="ldapServer" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg>
<list>
<value>${ldap.url1}</value>
...
</list>
</constructor-arg>
<constructor-arg value="${ldap.basedn}"</constructor-arg>
<property name="referral" value="${ldap.referral}" />
<property name="baseEnvironmentProperties">...</property>
<property name="userDn" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
</bean>
I am using Springframework 3.1.2. The problem is, there are constructor arguments, which I want to change and not affect other running jobs. I tried playing with Scoped proxy, but not to much success yet:
<bean id="ldapServer" scope="prototype" ...>
<aop:scoped-proxy/>
I was successful though to get ldapServer to reinstantiate, when using prototype scope by running this piece of code:
#Controller
public class LDAPSettingsController implements ApplicationContextAware {
public ModelAndView handleRequest(...) {
DefaultSpringSecurityContextSource ldap;
ldap = context.getParentBeanFactor().getBean("ldapServer");
System.out.println(ldap.hashCode());
return new ModelAndView(new RedirectView('login.jsp'));
}
...
}
Are scopes and proxies here the way to go, or is the another mechanism in Spring to reflect configuration changes into a running program instance?
UPDATE: Clear up the question.
UPDATE: The root problem with the AOP proxies was following root exception:
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
What worked was adding proxy-target-class="false" attribute to the <aop:scoped-proxy/> tag. I created a new scope, which works better than prototype - It destroys beans on settings update. Now I have this in my beans.xml:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="ldap">
<ref bean="ldapScope" />
</entry>
</map>
</property>
</bean>
<bean id="ldapScope" class="com.myapp.SettingsScope" />
<bean id="ldapServer" scope="ldap" ...>
<aop:scoped-proxy proxy-target-class="false"/>
<constructor-args>
<list><value>${ldap.url1}</value> .. </list>
</constructor-args>
...
</bean>
I also have a controller for LDAP settings into which I inject ldapScope and I call a method which destroys current life-cycle objects and starts a new life-cycle every time, user presses the apply button.
PS: Not sure if I handle the life-cycle "re-start" in the right way - people my way to look for auto-start beans and start them after such event happens (i.e.: Setting -> Apply)

Conditional initialization of classes in spring

I have a service which refers to a single source.
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref="DataSource1" />
</bean>
<bean id="DataSource1" class="com.source.impl.DataSource1">
<constructor-arg ref="DBDataSource"/>
<constructor-arg value="xyz"/>
</bean>
<bean id="DataSource2" class="com.source.impl.DataSource2">
<constructor-arg ref="MsgDataSource"/>
<constructor-arg value="xyz"/>
</bean>
Now if i want to perform a conditional check and my service should be able listen to particular source based on a input variable something like below.
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref=" $VARIABLE == true ? DataSource1 : DataSource2" />
</bean>
I did tried SPEL however no luck. I am beginner in spring. Any help will be appreciated.
Thanks.
There are many solutions. Here are two: You can use profiles for this. Define two profiles, define the DataSource beans with the same name but different profiles. (docs)
Alternatively, you can use a single bean and a static factory method (docs).
<bean id="DataSource" class="com.source.impl.DataSourceFactory"
factory-method="createInstance"/>
Inside of DataSourceFactory.createInstance(), you can check the flag and then create the correct data source in plain Java.
The latter is a bit easier to understand, IMO. Using profiles allows you to keep everything in XML (but you should really consider switching to the Java Configuration). The drawback with profiles is that you must not forget to activate at least one of the bean won't be defined.
A third option is to use three XML files and then modify the list of XML files that should be parsed when you pass it to the ApplicationContext. But that only works if you have control over this part of the code.
Assuming you are using Spring 3.1 or later, Spring Profiles may be the best solution.
Using the example of Production and Dev/QA environments, common bean declarations go in a shared file
<beans>
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref="DataSource" />
</bean>
</beans>
A separate configuration contains production references
<beans profiles="prod">
<bean id="DataSource" class="com.source.impl.DataSource1">
<constructor-arg ref="DBDataSource"/>
<constructor-arg value="xyz"/>
</bean>
</beans>
Another contains dev references
<beans profile="dev">
<bean id="DataSource" class="com.source.impl.DataSource2">
<constructor-arg ref="MsgDataSource"/>
<constructor-arg value="xyz"/>
</bean>
</beans>
To activate the given profile add -Dspring.profiles.active=prod to your JVM arguments
You can find more info here
Another approach uses factory methods.
<bean id="DataSource" class="com.source.impl.DataSourceFactory" factory-method="getInstance">
<constructor-arg value="#{VARIABLE}" />
</bean>
The above fragment assumes that you want your factory method to explcitly invoke the constructor of each of your services. If you dead set on using Spring to create the instances you can pass each datasource implementation as constructor arguments and use the constructor method as a simple dispatcher.
You need something like this:
<constructor-arg
ref="#{systemProperties.variable == 'true' ? 'DataSource1' : 'DataSource2'}" />
where "variable" is set like -Dvariable=true.

can spring container XML config reference use another bean'property

Here I am writing a spring application, here I want to do is like this:
<bean id="sqlClient" class="com.braoda.dao.sqclient.SqlclientWapper">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao" class="com.braoda.dao.user.UserDaoImpl">
<property name="sqlSession" ref="***sqlClient.SqlSessionFactoryBean***" />
As the code like, I want use the spring Xml property config from "ref", but "ref" is not a bean but a bean's property.
is this illegal in spring or we can not use spring like this.
Yes, it is possible.
have a look at http://forum.spring.io/forum/spring-projects/container/35869-reference-bean-property-within-reference
which shows code like <property name="username" value="${local.username}"/>
It is possible using the #{...} notation:
<property name="sqlSessionFactory" value="#{sqlMapClient.getSqlSessionFactory()}"/>
Note:
${...} may be used to substitute Spring property names for their value
#{...} may be used to let Spring evaluate expressions
More details at http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html.

Is it possible to specify a context property placeholder at runtime

I have a standalone jar that uses spring. The config in my spring xml uses placeholders of which I've been replacing when compiling with maven. Example spring config:
<bean id="foo" class="package.Foo">
<property name="host" value="${db.host}" />
</bean>
Instead of replacing ${db.host} using maven I'd like to pass in a properties file at runtime, e.g.
java -jar Application.jar productionDB.properties
This would allow me to switch the db host at runtime by passing in the production db properties file or the testing db properties file.
Is it possible to do this or are there any better ways of achieving the same goal?
You could specify your property file as a System Property, e.g.:
java -jar Application.jar -DappConfig=/path/to/productionDB.properties
Then you should be able to reference that in your application context:
<context:property-placeholder location="file:${appConfig}"/>
<bean id="foo" class="package.Foo">
<property name="host" value="${db.host}" />
</bean>
You could use a PropertyPlaceholderConfigurer to use a .properties file to pass in the required variables.
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:productionDB.properties</value>
</list>
</property>
</bean>
You can leave your bean declaration as is. The properties will be automatically taken from the productionDB.properties file.
There are a few options:
Set your resources via your container's JNDI and use Spring's <jee:jndi-lookup/>.
Use Spring's <context:property-placeholder location="classpath:/myProps.properties" />. I prefer this short-hand over the "full" bean definition because Spring will automatically use the correct implementation (PropertyPlaceholderConfigurer for Spring < 3.1, or PropertySourcesPlaceholderConfigurer for Spring 3.1+). Using this configuration, you would just drop the myProps.properties at the root of your classpath (${TOMCAT_HOME}/lib for example).
You can pass the values using the context:property-placeholder. So your setup would be something like:
<context:property-placeholder location="file://opt/db.properties"/>
Then when you are wiring up your Foo service, you can use the property names in your config, such as
<bean id="foo" class="package.Foo">
<property name="host" value="${db.host}" />
</bean>
Then just use the different set of files for each environmnet
See the spring docs for more details.

Categories

Resources