Настройка Grails / Spring Locale во время входа в Spring Security - как? - PullRequest
4 голосов
/ 27 октября 2011

В моем приложении 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 возвращаетноль.

Как установить новую локаль?

Ответы [ 2 ]

1 голос
/ 09 февраля 2015

У меня возникла та же проблема, и я нашел обходной путь. 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)
        }
    }
}

Это самый простой способ. Как видите, я использовал закрытие обратного вызова вместо того, чтобы объявлять отдельный класс и регистрировать бин в resources.groovy. Также стоит упомянуть, что вы можете сохранить поле Locale вместо двух отдельных полей для языка и страны.

И эта строка

User user = User.findByUsername(event.authentication.name)

Можно переписать на более эффективный

User user = User.get(event.authentication.principal.id)

он будет использовать кэш второго уровня Hibernate по идентификатору и будет безопасен для чувствительных к регистру имен пользователей.

1 голос
/ 27 октября 2011

Вместо того, чтобы делать это на этапе входа в систему, вы должны создать реализацию LocaleResolver, которая может определить правильную Locale для использования для данного HttpServletRequest.

Ваше приложение должно знать, как разрешать язык для каждого последующего запроса, который делает пользователь.Установка Locale в LocaleResolver или LocaleContextHolder вручную влияет только на ThreadLocal, хранящим Locale для запроса current .Новый запрос не будет иметь тот же ThreadLocal и будет видеть неустановленный языковой стандарт.

Это должно быть тривиально создать реализацию, которая получает входящий в систему UserDetails из контекста Spring Security и находит локальдля пользователя (или вы можете сохранить данные в сеансе и т. д., выбор за вами).

...