保持Spring Security会话超时的语言环境

时间:2014-06-20 12:25:29

标签: java spring java-ee spring-mvc spring-security

我使用的是Spring Security 3.0.2,我有这个配置

    <security:form-login
        login-processing-url="/resources/j_spring_security_check"
        login-page="/login"
         authentication-failure-handler-ref="authErrorHandler" authentication-success-handler-ref="authCorrectHandler" />
    <security:logout logout-success-url="/index.jsp" invalidate-session="false" />
    <security:remember-me />
    <security:session-management invalid-session-url="/login/sessionExpired" >
        <security:concurrency-control max-sessions="1"
            error-if-maximum-exceeded="true" />
    </security:session-management>

当我使用某个区域设置登录时,一切顺利,但是当会话到期时,Spring Security会清除会话并默认使用区域设置创建新的匿名会话(并按预期转到登录页面)。结果是用户区域设置为LOST。

如何在Spring Security 3.0.2中使会话到期时保留用户区域设置?

我使用localeChangeInterceptor设置语言环境,如下所示:

    <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <property name="paramName" value="language" />
    </bean>

和SessionLocaleResolver作为区域设置解析器:

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
    <property name="defaultLocale" value="es" />
</bean>

编辑 - 为我的需要解决

我终于在我自己的 LocaleChangeInterceptor 中设置了一个 cookie ,它从 HandlerInterceptorAdapter 扩展,在中写下来preHandle 方法:

     LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
     if (localeResolver == null) {
       throw new IllegalStateException("No LocaleResolver found.");
     }
     Cookie mylang = new Cookie("mylang", locale.getLanguage() + "_" + locale.getCountry());
     mylang.setMaxAge(86400); 
     response.addCookie(mylang);

     localeResolver.setLocale(request, response, locale);

然后在 / sessionExpired 控制器点,我获得了Cookie值:

public String sessionExpired(HttpServletRequest request, HttpServletResponse response, Model model, 
        @CookieValue(value = "mylang", defaultValue = "es_ES") String myLang) throws Exception {
    model.addAttribute("mylang", myLang);
    LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);

    StringTokenizer st = new StringTokenizer(myLang, "_");

    String language = "";
    String country = "";

    try {
        language = (String) st.nextElement();
        country = (String) st.nextElement();
    } catch (Exception e) {
        throw new Exception("Error locale");
    }

    Locale locale = new Locale(language, country); 
    localeResolver.setLocale(request, response, locale);
    return "sessionExpired";

在这种情况下,无需使用数据库作为临时存储。

1 个答案:

答案 0 :(得分:2)

从逻辑上讲,您似乎无法使用会话来跟踪区域设置。使用请求参数language设置区域设置,该参数将通过会话清除。创建新会话时,区域设置默认为es给出的localeResolver。我可以想到的一种方法是将用户首选项存储在数据库中,并在后续登录时从那里检索

同样由@M建议。 Deinum:

如果你对cookie没问题,可以使用CookieLocaleResolver来保留cookie中的选择。否则,实现自己的LocaleResolver存储/从数据库检索。