在我的Grails 1.3.7应用程序中,我将用户的语言和国家/地区存储在域类中。
在(Spring Security)登录期间,我想将用户会话的区域设置设置为为该用户存储的语言/国家/地区。
我正在实现我的自定义侦听器,在grails-app / spring / resources.groovy中注册:
class MyListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> {
def config = org.codehaus.groovy.grails.commons.ConfigurationHolder.config
void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
User user = User.findByUsername(event.authentication.name)
Locale locale = new Locale(user.getLanguage(), user.getCountry())
LocaleContextHolder.setLocale(locale)
HttpServletRequest request = SecurityRequestHolder.request
HttpServletResponse response = SecurityRequestHolder.response
LocaleResolver locRes = RequestContextUtils.getLocaleResolver(request)
locRes.setLocale(request, response, locale)
}
}
我的问题是RequestContextUtils.getLocaleResolver返回null。
如何设置新的区域设置?
答案 0 :(得分:1)
您应该创建一个LocaleResolver
实现,而不是在登录步骤中执行此操作,该实现可以确定用于给定Locale
的正确HttpServletRequest
。
您的应用需要知道如何为用户发出的每个后续请求解析区域设置。手动设置LocaleResolver或LocaleContextHolder中的Locale只会影响存储当前请求的Locale的ThreadLocal。新请求不会具有相同的ThreadLocal,并且会看到未设置的区域设置。
创建一个实现,从Spring Security上下文获取当前登录的UserDetails
并找到用户的Locale(或者您可以在Session中存储详细信息,等等,这应该是微不足道的。选择取决于你)。
答案 1 :(得分:1)
我遇到了同样的问题并做了一个解决方法。默认情况下,LocaleResolver为SessionLocaleResolver
。显然,从名称来看,它通过键SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME
将语言环境存储在会话中。
因此,您可以在用户登录后手动设置它。
这是我Config.groovy
grails.plugin.springsecurity.useSecurityEventListener = true
grails.plugin.springsecurity.onInteractiveAuthenticationSuccessEvent = { InteractiveAuthenticationSuccessEvent event, appCtx ->
User.withNewSession {
User user = User.get(event.authentication.principal.id)
if (user?.locale) {
HttpServletRequest request = SecurityRequestHolder.request
// SmartConfigLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME if you use locale-configuration plugin
WebUtils.setSessionAttribute(request, SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, user.locale)
}
}
}
这是最简单的方法。如您所见,我使用callback closure而不是在resources.groovy
中声明单独的类和注册bean。
另外最糟糕的是,您可以保存Locale
字段,而不是语言和国家/地区的两个单独字段。
这一行
User user = User.findByUsername(event.authentication.name)
您可以重写为更高效的
User user = User.get(event.authentication.principal.id)
它将通过id使用Hibernate二级缓存,对于区分大小写的用户名将是安全的。