bhiles
bhiles

Reputation: 123

Stormpath Spring Security Java config

I'm migrating a Spring XML configured application to Spring Java configured one. I'm new to Java configuration haven't found what the configuration should look like. I'm looking at their (Stormpath's) example app and it is XML based configuration.

Can anyone help me translate their application over to a Java configured application? I can get it from there if I have a base to work from.

Upvotes: 2

Views: 908

Answers (1)

mario
mario

Reputation: 1162

The closest to a 1:1 mapping would be:

The servlet-context.xml config would be translated to this:

/**
 * Spring JavaConfig defining this Servlet's request-processing infrastructure
 */
@Configuration
@EnableWebMvc
@ComponentScan("com.stormpath.spring.security.example.controller")
public class ServletContextConfig {

    @Bean
    InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }

}

root-context.xml would be:

/**
 * Spring JavaConfig defining shared resources visible to all other web components.
 */
@Configuration
public class RootContextConfig {

    //Let's create the Stormpath client using the apiKey.properties file from the User's home folder.
    @Bean
    ClientFactory stormpathClient(CacheManager cacheManager) {
        ClientFactory clientFactory = new ClientFactory();
        clientFactory.setApiKeyFileLocation(System.getProperty("user.home") + File.separator + ".stormpath" + File.separator + "apiKey.properties");
        clientFactory.setCacheManager(cacheManager);
        return clientFactory;
    }

    //Let's instantiate the Stormpath Authentication Provider
    @Bean
    @Autowired
    public StormpathAuthenticationProvider stormpathAuthenticationProvider(Client client, String applicationRestUrl) throws Exception {
        StormpathAuthenticationProvider stormpathAuthenticationProvider = new StormpathAuthenticationProvider();
        stormpathAuthenticationProvider.setClient(client);
        stormpathAuthenticationProvider.setApplicationRestUrl(applicationRestUrl);
        return stormpathAuthenticationProvider;
    }

    //Bean for CustomData Management
    @Bean
    CustomDataManager customDataManager() {
        return new CustomDataManager();
    }

    @Bean
    WildcardPermissionEvaluator permissionEvaluator() {
        return new WildcardPermissionEvaluator();
    }

    @Bean
    MethodSecurityExpressionHandler methodExpressionHandler(WildcardPermissionEvaluator permissionEvaluator) {
        DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
        methodSecurityExpressionHandler.setPermissionEvaluator(permissionEvaluator);
        return methodSecurityExpressionHandler;
    }

    @Bean
    DefaultWebSecurityExpressionHandler webExpressionHandler(WildcardPermissionEvaluator permissionEvaluator) {
        DefaultWebSecurityExpressionHandler webSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
        webSecurityExpressionHandler.setPermissionEvaluator(permissionEvaluator);
        return webSecurityExpressionHandler;
    }

    @Bean
    CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        Collection<Cache> caches = new ArrayList<Cache>();
        caches.add(applicationCache().getObject());
        caches.add(accountCache().getObject());
        caches.add(groupCache().getObject());
        caches.add(customDataCache().getObject());
        cacheManager.setCaches(caches);
        return cacheManager;
    }

    @Bean
    ConcurrentMapCacheFactoryBean applicationCache(){
        ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
        cacheFactoryBean.setName("com.stormpath.sdk.application.Application");
        return cacheFactoryBean;
    }

    @Bean
    ConcurrentMapCacheFactoryBean accountCache(){
        ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
        cacheFactoryBean.setName("com.stormpath.sdk.account.Account");
        return cacheFactoryBean;
    }

    @Bean
    ConcurrentMapCacheFactoryBean groupCache(){
        ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
        cacheFactoryBean.setName("com.stormpath.sdk.group.Group");
        return cacheFactoryBean;
    }

    @Bean
    ConcurrentMapCacheFactoryBean customDataCache(){
        ConcurrentMapCacheFactoryBean cacheFactoryBean = new ConcurrentMapCacheFactoryBean();
        cacheFactoryBean.setName("com.stormpath.sdk.directory.CustomData");
        return cacheFactoryBean;
    }

}

and spring-security.xml would be:

/**
 * Spring JavaConfig defining Spring Security settings.
 */
@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    //The HREF to the Stormpath Application
    final String applicationRestUrl = "REPLACE_ME_WITH_YOUR_STORMPATH_APP_REST_URL";

    //Let's specify some role here so we can later grant it access to restricted resources
    final String roleA = "REPLACE_ME_WITH_YOUR_STORMPATH_GROUP_ALLOWED_TO_ACCESS_THIS_SECURED_RESOURCE";

    @Autowired
    private AuthenticationProvider stormpathAuthenticationProvider;

    //The access control settings are defined here
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()
                    .and()
                .authorizeRequests()
                    .accessDecisionManager(accessDecisionManager())
                    .antMatchers("/account/*").hasAuthority(roleA)
                    .and()
                .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/index.jsp")
                    .and()
                .httpBasic()
                .and()
                .csrf().disable();
    }


    @Bean
    public AuthenticationManager getAuthenticationManager() throws Exception {
        return this.authenticationManagerBean();
    }

    //Let's add the StormpathAuthenticationProvider to the AuthenticationManager
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .authenticationProvider(stormpathAuthenticationProvider);
    }

    //Prevents the addition of the "ROLE_" prefix in authorities
    @Bean
    public WebExpressionVoter webExpressionVoter() {
        WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
        return webExpressionVoter;
    }

    @Bean
    public AffirmativeBased accessDecisionManager() {
        AffirmativeBased affirmativeBased = new AffirmativeBased(Arrays.asList((AccessDecisionVoter) webExpressionVoter()));
        affirmativeBased.setAllowIfAllAbstainDecisions(false);
        return affirmativeBased;
    }

    @Bean
    public String getApplicationRestUrl() {
        return this.applicationRestUrl;
    }

}

Then, in web.xml you should do the following changes in order for the new JavaConfig to be picked up.

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

to

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

and finally:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/root-context.xml,
        /WEB-INF/spring-security.xml
    </param-value>
</context-param>

for this:

<context-param>
    <param-name>contextClass</param-name>
    <param-value>
        org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        com.stormpath.spring.security.example.config.ServletContextConfig,
        com.stormpath.spring.security.example.config.RootContextConfig,
        com.stormpath.spring.security.example.config.SpringSecurityConfig
    </param-value>
</context-param>

You will also need to add this dependency in your project:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

You can see a fully-migrated working version in their java_config branch: https://github.com/stormpath/stormpath-spring-security-example/tree/java_config

Upvotes: 4

Related Questions