views:

69

answers:

3

I have a web application that works with several different configurations of Spring Security already. However, these difference configuration are all setup within my applicationContext configuration file. Therefore, in order to tweak these at a customer site, these would have to be modified INSIDE the WAR file. If customers manually modify the WAR file, then they'll lose their changes after redeploying a new WAR.

Is there a way to externalize this configuration? Is there a way I can load the configuration using JNDI somehow?

A: 

You can add a org.springframework.beans.factory.config.PropertyPlaceholderConfigurer, which references an external file, then use the ${key} syntax without your Spring configuration files to reference key/value pairs in the externalized property file.

Another solution is to specify an absolute path in your web.xml to reference a Spring contextConfigLocation.

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>/absolute_path/ldap.xml, /WEB-INF/context/dao-context.xml</param-value>
</context-param> 
BacMan
I am familiar with that capability, but I don't think I can use it to add/remove an LDAP server authentication provider to the list of authentication providers, for example.
HDave
You can't use this mechanism to configure providers. Another approach is to create an externalized security context XML file. You can reference files outside your war with Spring.
BacMan
Bacman -- this sounds interesting - can you provide a hint on how to reference externalized context XML file?
HDave
A: 

Alternatively you can use org.springmodules.commons.configuration.CommonsConfigurationFactoryBean to store and retrieve your configuration as key, value pair in database table

    <bean name="DatabaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration">
            <constructor-arg type="javax.sql.DataSource" ref="dataSource"/>
            <constructor-arg index="1" value="CONFIG_TABLE_NAME"/>
            <constructor-arg index="2" value="KEY_COLUMN_NAME"/>
            <constructor-arg index="3" value="VALUE_COLUMN_NAME"/>
    </bean>
KZameer
Here is the full configuration
KZameer
+1  A: 

It's an interesting question. Since Spring Security should be configured in root webapp context, you can't externalize its configuration to other contexts. Also you can't change the set of config resources from inside the context. So, you should do it from outside:

  • You can use a well-known file system location:

     <context-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>
             /WEB-INF/applicationContext.xml
             file:///C:\config.xml
         </param-value>
     </context-param>
    
  • System properties are resolved in contextConfigLocation, so you can use it:

     <context-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>
             /WEB-INF/applicationContext.xml
             file:///${configPath}
         </param-value>
     </context-param>
    

    and -DconfigPath=...

  • You can override XmlWebApplicationContext.getResource() and implement whatever you want:

    public class MyXmlWebApplicationContext extends XmlWebApplicationContext {
        private static final String JNDI_PREFIX = "jndi:/";        
        @Override
        public Resource getResource(String location) {
            if (location.startsWith(JNDI_PREFIX)) return getJndiResource(location);
            else return super.getResource(location);
        }
        protected Resource getJndiResource(String location) { ... }
    }
    

    and

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext.xml
            jndi:/...
        </param-value>
    </context-param>        
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>com.example.MyXmlWebApplicationContext</param-value>
    </context-param>
    
axtavt
If I were to go the JNDI route, I assume I would have to programmatically configure spring security, yes?
HDave
BTW - I am concerned about the idea of opening a file on the file system. I am not sure that some customers will allow this in a JEE environment, and also I am unsure as to how this will interplay with clustering.
HDave
@HDave: No, the third approach shows how you can create your own way to access XML configs (as well as other `Resource`s).
axtavt
I think I get it. So the getResource uses a JNDI name to retrieve the JNDI object which is an XML String, yes?
HDave
@HDave: Yes, you may implement it this way if your application server supports it.
axtavt