Search code examples
springspring-securityspring-webflowspring-webflow-2

Spring webflow overwrite Spring security request rules?


Project use SWF 2.4.1 and SSec 4. I specified a failUrl on spring security for errors on login and a transition on webflow if evaluate expression fail. In this case SWF redirection is priority to SSec redirection. I wonder if there is some way to omit/change this behavior because I would follow spring security rules automatically without to create rules on spring webflow.

security rules

http
    .antMatcher("/spring/**/*.xhtml")
        .exceptionHandling().authenticationEntryPoint(new AccessDenyEntryPoint())
    .and()
        .requestCache().requestCache(requestCache())
    .and()
    .authorizeRequests()
        .antMatchers("/spring/resources/**","/spring/login","/spring/signup",
                "/spring/main","/spring/error","/spring/group").permitAll()
        .antMatchers("/spring/myprofile").hasRole("USER")
        .antMatchers("/spring/profilegroup").hasRole("MEMBER")
        .antMatchers("/spring/admin").hasRole("ADMIN")
        .antMatchers("/spring/**/*.xhtml").denyAll()
        .anyRequest().authenticated()
    .and()       
    .formLogin()
        .loginPage("/spring/login")
        .defaultSuccessUrl("/spring/main",true)
        .failureUrl("/spring/login?login_error=1")
    .and()
    .logout()
        .logoutSuccessUrl("/spring/home")
        .deleteCookies("JSESSIONID")
    .and()
        .rememberMe().userDetailsService(customDetailsService)
    .and()
    .exceptionHandling().accessDeniedPage("/spring/error?error_code=1")
    .and()


    // Disable CSRF (won't work with JSF) but ensure last HTTP POST request is saved
    // See https://jira.springsource.org/browse/SEC-2498

    .csrf().disable()
    .requestCache()
        .requestCache(new HttpSessionRequestCache())
     .and()
     .sessionManagement()
        .sessionFixation().changeSessionId()
        .invalidSessionUrl("/spring/main")
        .sessionAuthenticationErrorUrl("/spring/error?error_code=4")
        .maximumSessions(1)
        .expiredUrl("/spring/error?error_code=2")
        .maxSessionsPreventsLogin(true);

Webflow rules

    <view-state id="login" view="login.xhtml">
    <transition on="entry" to="connect"/>
    <transition on="recoveryPass" to="recovery" />
</view-state>

<action-state id="connect">
    <evaluate expression="login.connect()" />
    <transition on="yes" to="connected" />
    <transition on="no" to="recovery" />
</action-state>

<view-state id="recovery" view="recovery.xhtml">

    <transition on="sendPass" to="login" />
    <transition on="return" to="login" />
    <transition on="error" />
</view-state>

<end-state id="finish" />

validation code

public String connect(){
    logger.entry("Login.connect()");

    try{
        Authentication request=new UsernamePasswordAuthenticationToken(getEmail(), getPassword());
        Authentication result=daoProvider.authenticate(request);
        SecurityContextHolder.getContext().setAuthentication(result);
    }catch (BadCredentialsException e) {
        //MessageRedirect.addFlashMesage("usuario.no.registrado","msg");
        return "no";
    }catch (LockedException e) {
        //MessageRedirect.addFlashMesage("usuario.bloqueado","msg");
        return "no";
    }catch (DisabledException e) {
        //MessageRedirect.addFlashMesage("usuario.desactivado","msg");
        return "no";
    }

    return "yes";
}

Solution

  • Real problem was I was setting secured control on spring security configuration and I should set their on flow definition. Create a custom form page/controller wasn't the problem and works properly and it's not necessary to set loginProccess if you are using a bean. So, configuration would be some like this

    Security config

        @Override
    protected void configure(HttpSecurity http) throws Exception {
    
        http
            .exceptionHandling().authenticationEntryPoint(new AccessDenyEntryPoint())
        .and()
            .exceptionHandling().accessDeniedHandler(new AccessDenyHandlerPoint())  
        .and()
            .authorizeRequests()
                .antMatchers("/spring/**/*.xhtml").denyAll()
        .and()     
        .formLogin()
            .loginPage("/spring/login")
            .loginProcessingUrl("/spring/loginProcess")
            .defaultSuccessUrl("/spring/main",true)
            .failureUrl("/spring/login?login_error=1")
        .and()
        .logout()
            .logoutUrl("/spring/logout")
            .logoutSuccessUrl("/spring/main")
            .deleteCookies("JSESSIONID")
    
        // Disable CSRF (won't work with JSF) but ensure last HTTP POST request is saved
        // See https://jira.springsource.org/browse/SEC-2498
       .and()
       .csrf().disable()
       .sessionManagement()
            .sessionFixation().changeSessionId()
            .invalidSessionUrl("/spring/error?error_code=1")
            .sessionAuthenticationErrorUrl("/spring/error?error_code=2")
            .maximumSessions(1)
            .expiredUrl("/spring/error?error_code=3")
            .maxSessionsPreventsLogin(true);
    
    }
    

    Flow definition

        <secured attributes="ROLE_USER" />
    
    <on-start>
        <evaluate expression="spaceBO.dao.getAll()" result="flowScope.spaces"/>
    </on-start>
    <view-state id="inicio" view="main.xhtml">
    
    </view-state>