spring-projects / spring-security

Spring Security
http://spring.io/projects/spring-security
Apache License 2.0
8.8k stars 5.9k forks source link

SEC-2609: Add an InvalidSessionStrategy implementation for JSF #2825

Open spring-projects-issues opened 10 years ago

spring-projects-issues commented 10 years ago

Mauro Molinari (Migrated from SEC-2609) said:

The only InvalidSessionStrategy implementation provided is SimpleRedirectInvalidSessionStrategy which simply does a redirect to the configured invalid session URL. However in a JSF environments there's a common problem for which people are usually creating various kind of workarounds: when a JSF component in a page protected by Spring Security makes an Ajax request and the server session is invalid (i.e. expired), the SimpleRedirectInvalidSessionStrategy sends a redirect response to the client-side code that generated the request. However, this plain redirect is not handled correctly by the JSF JavaScript code and no actual redirection is performed. The actual result is that the user clicks on components in the page and nothing happens.

The correct way to handle these kind of requests is to reply with a proper Ajax response with the redirect URL, as described in the JSF specification:

<?xml version="1.0" encoding="UTF-8"?>
<partial-response>
  <redirect url="${redirectUrl}" />
</partial-response>

There are a couple of independent implementations around that do this, however having a suitable InvalidSessionStrategy built in in Spring Security would be very useful and would save a lot of headaches to many people.

As a starting point, two examples of a proper implementation are:

Please note that improving the <security:session-management> namespace tag to be able to specify a proper InvalidSessionStrategy would also help a lot in these scenarios ;-)

gersonsosa commented 8 years ago

I have tried to implement the second suggestion mentioned

https://gist.github.com/banterCZ/5160269 : I don't have tested this, but it implements the new InvalidSessionStrategy

But It does not redirect either, I'm using annotations to configure my webapp:

http.addFilterBefore(sessionManagmentFilter(), SessionManagementFilter.class);
....
@Bean
public SessionManagementFilter sessionManagmentFilter() {
    SessionManagementFilter sessionManagementFilter =
            new SessionManagementFilter(httpSessionSecurityContextRepository());
    sessionManagementFilter.setInvalidSessionStrategy(JsfRedirectStrategy());
    return sessionManagementFilter;
}

@Bean
public HttpSessionSecurityContextRepository httpSessionSecurityContextRepository() {
    return new HttpSessionSecurityContextRepository();
}

@Bean
public JsfRedirectStrategy JsfRedirectStrategy() {
    JsfRedirectStrategy jsfRedirectStrategy =
            new JsfRedirectStrategy();
    jsfRedirectStrategy.setInvalidSessionUrl("/login.xhtml");
    return jsfRedirectStrategy;
}

Using debugging I see the redirection strategy gets the request when the session is invalid; but somehow the response to the browser is Request Method:POST Status Code:403 Forbidden instead of redirecting to login page.

Any help would be welcome Thanks

mauromol commented 8 years ago

Meanwhile I have also used the new InvalidSessionStrategy implementation I linked before with success. It's working fine for me. However, I'm using XML to configure the whole thing. Here is an excerpt:

<bean id="invalidSessionStrategy"
    class="mypackage.JsfRedirectStrategy">
    <property name="invalidSessionUrl" value="${sessionExpiredPage}" />
</bean>

<bean id="sessionManagementFilter"
    class="org.springframework.security.web.session.SessionManagementFilter">
    <constructor-arg ref="securityContextRepository" />
    <constructor-arg ref="sessionAuthenticationStrategy" />
    <property name="invalidSessionStrategy" ref="invalidSessionStrategy" />
</bean>

<bean id="accessDeniedHandler"
    class="org.springframework.security.web.session.InvalidSessionAccessDeniedHandler">
    <constructor-arg ref="invalidSessionStrategy" />
</bean>

<bean id="exceptionTranslationFilter"
    class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <constructor-arg ref="authenticationEntryPoint" />
    <constructor-arg ref="requestCache" />
    <property name="accessDeniedHandler" ref="accessDeniedHandler" />
</bean>

Hope this helps.