【问题标题】:Keep locale on Spring Security session timeout保持 Spring Security 会话超时的语言环境
【发布时间】:2014-08-11 05:02:37
【问题描述】:

我正在使用 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 会清除会话并默认使用语言环境创建新的匿名会话(并按预期进入登录页面)。结果是用户语言环境丢失。

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";

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

【问题讨论】:

  • 你能发布一下你是如何设置语言环境的吗?
  • 更新的帖子显示了我如何设置语言环境
  • 从逻辑上讲,您似乎不能使用会话来跟踪区域设置。区域设置使用请求参数language 设置,该参数将随会话清除。创建新会话时,区域设置默认为es,由localeResolver 给出。我能想到的一种方法是将用户偏好存储在数据库中,并在后续登录时从那里检索。
  • 正确,我就是这么想的。但我希望 Spring Security 可能有任何机制来保留而不是破坏语言环境。
  • 您正在使用SessionLocaleResolver,显然将其存储在会话中。没有会话没有存储的语言环境。如果您对 cookie 没问题,请使用 CookieLocaleResolver,它将选择保留在 cookie 中。否则实现你自己的LocaleResolver,它从数据库中存储/检索。

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


【解决方案1】:

从逻辑上讲,您似乎不能使用会话来跟踪语言环境。区域设置使用请求参数language 设置,该参数将随会话清除。创建新会话时,区域设置默认为es,由localeResolver 给出。我能想到的一种方法是将用户偏好存储在数据库中,并在后续登录时从那里检索

也正如@M 所建议的那样。迪南:

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

【讨论】:

  • 我不知道为什么,但 CookieLocaleResolver 本身在登录时对我不起作用,请保留以前存储的语言环境而不是当前语言环境。无论如何,会话超时按预期工作并保持语言环境。让我在登录时检查问题。
  • 我已经用适合我的解决方案更新了这个问题。谢谢大家的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-27
  • 2016-08-03
  • 2021-07-04
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多