【发布时间】: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