Detect session Timeout in Ajax Request in Spring MVC
Nie widzę dobrego przykładu/odpowiedzi na to, jak odesłać niektóre dane z żądania ajax, gdy sesja się skończyła. Odsyła HTML strony logowania i chcę albo wysłać json lub kod stanu, który mogę przechwycić.
4 answers
Najprostszym sposobem na to jest użycie filtra adresów URL żądań AJAX.
W poniższym przykładzie po prostu wysyłam kod odpowiedzi HTTP 500 z ciałem odpowiedzi wskazującym limit czasu sesji, ale możesz łatwo ustawić kod odpowiedzi i ciało na to, co jest bardziej odpowiednie dla Twojego przypadku..
package com.myapp.security.authentication;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ExpiredSessionFilter extends GenericFilterBean {
static final String FILTER_APPLIED = "__spring_security_expired_session_filter_applied";
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (request.getAttribute(FILTER_APPLIED) != null) {
chain.doFilter(request, response);
return;
}
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "SESSION_TIMED_OUT");
return;
}
chain.doFilter(request, response);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-11 08:20:23
Oto podejście, które moim zdaniem jest dość proste. Jest to kombinacja podejść, które zaobserwowałem na tej stronie. Napisałem o tym wpis na blogu: http://yoyar.com/blog/2012/06/dealing-with-the-spring-security-ajax-session-timeout-problem/
Podstawową ideą jest użycie prefiksu URL api (tj. / api / secured), jak sugerowano powyżej, wraz z punktem wejścia uwierzytelniania. To proste i działa.
Oto punkt wejścia uwierzytelniania:
package com.yoyar.yaya.config;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class AjaxAwareAuthenticationEntryPoint
extends LoginUrlAuthenticationEntryPoint {
public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
super(loginUrl);
}
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
boolean isAjax
= request.getRequestURI().startsWith("/api/secured");
if (isAjax) {
response.sendError(403, "Forbidden");
} else {
super.commence(request, response, authException);
}
}
}
I oto co wchodzi w kontekst wiosenny xml:
<bean id="authenticationEntryPoint"
class="com.yoyar.yaya.config.AjaxAwareAuthenticationEntryPoint">
<constructor-arg name="loginUrl" value="/login"/>
</bean>
<security:http auto-config="true"
use-expressions="true"
entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/api/secured/**" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/logout" access="permitAll"/>
<security:intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/" access="permitAll"/>
<security:form-login login-page="/login"
authentication-failure-url="/loginfailed"
default-target-url="/login/success"/>
<security:access-denied-handler error-page="/denied"/>
<security:logout invalidate-session="true"
logout-success-url="/logout/success"
logout-url="/logout"/>
</security:http>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-25 02:32:55
Używam tego samego rozwiązania przez @ Matt w backendzie. Jeśli używasz angularJs z przodu, dodaj poniżej interceptor w angular $ http, aby pozwolić przeglądarce faktycznie zrobić przekierowanie do strony logowania.
var HttpInterceptorModule = angular.module('httpInterceptor', [])
.config(function ($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
})
.factory('myInterceptor', function ($q) {
return {
'responseError': function(rejection) {
// do something on error
if(rejection.status == 403 || rejection.status == 401) window.location = "login";
return $q.reject(rejection);
}
};
});
Zauważ, że poniższy wiersz jest potrzebny tylko jeśli używasz AngularJs po wersji 1.1.1 (angularJS usunął nagłówek "X-Requested-With" z tej wersji)
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 08:50:37
Ponieważ wszystkie obecne odpowiedzi mają już kilka lat, podzielę się moim rozwiązaniem, które obecnie pracuję w aplikacji Spring Boot REST:
@Configuration
@EnableWebSecurity
public class UISecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.exceptionHandling.authenticationEntryPoint(authenticationEntryPoint());
...
}
private AuthenticationEntryPoint authenticationEntryPoint() {
// As a REST service there is no 'authentication entry point' like MVC which can redirect to a login page
// Instead just reply with 401 - Unauthorized
return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
}
Podstawową przesłanką jest to, że nadpisuję punkt wejścia uwierzytelniania, który domyślnie wysyłał przekierowanie do mojej nieistniejącej strony logowania. Teraz odpowiada, wysyłając 401. Spring domyślnie tworzy również obiekt JSON o standardowej odpowiedzi na błędy, który również zwraca.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-11 16:57:47