在Spring Security登录期间设置Grails / Spring Locale - 如何?

时间:2011-10-27 11:33:49

标签: java spring grails spring-security locale

在我的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。

如何设置新的区域设置?

2 个答案:

答案 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二级缓存,对于区分大小写的用户名将是安全的。