Spring security + i18n = как заставить работать вместе? - PullRequest
6 голосов
/ 12 декабря 2011

Мой первый вопрос здесь, и я постараюсь быть конкретным.Я совсем новичок в Spring, и я пытаюсь создать довольно простую систему бронирования (но это на самом деле не имеет значения).Важно то, что я создаю какой-то базовый шаблон, который затем заполняю реальными веб-страницами.Приложение работает на Hibernate, MySQL, я также настроить i18n и Spring Security.Проблема в том, что я не могу изменить свой язык.Единственное, что работает, это изменение по умолчанию.Сначала я просмотрел Web A LOT и обнаружил, что использование i18n вместе с Spring Security сложнее, чем обычно.Я обнаружил, что мне нужен дополнительный фильтр:

<filter>
    <filter-name>localizationFilter</filter-name>
    <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>localizationFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Я обнаружил, что этот фильтр действительно обрабатывается перед защитным, однако он не анализирует запрос в форме: http://someserver.com/bla/home?locale=en.Я отладил его, и кажется, что он не создан для этой цели (и это то, что мне нужно).Это взято из весенних примеров "контактов", однако в этом примере я не смог найти никакого кода, который на самом деле предназначался для изменения языка.В результате он просто не работает.Он всегда пытается изменить локаль на мою по умолчанию.Хорошая новость заключается в том, что если в режиме отладки я вручную изменил локаль-набор на другой, он работал нормально, поэтому я чувствовал надежду в моем сердце ...; -)

Тогда я нашел несколькоДругой способ - создав собственный фильтр.Что я сделал, так это слил найденный пример (не помню автора) и способ создания RequestContextFilter.В конце концов, RequestContextFilter работает нормально - просто не разбирайте мои запросы.Это код нового фильтра:

public class InternationalizationFilter extends OncePerRequestFilter {

@Override
public void destroy() {
    // TODO Auto-generated method stub

}


@Override
protected void doFilterInternal(final HttpServletRequest request,
        final HttpServletResponse response, final FilterChain filterChain)
        throws ServletException, IOException {
    final String newLocale = request.getParameter("locale");
    if (newLocale != null) {
        final Locale locale = StringUtils.parseLocaleString(newLocale
                .toLowerCase());
        LocaleContextHolder.setLocale(locale);
    }
    try {
        filterChain.doFilter(request, response);
    } finally {

        LocaleContextHolder.resetLocaleContext();
    }
}

}

Как видите, локаль параметра запроса анализируется и локаль установлена.Есть 2 проблемы: 1. После отправки запроса xxxxx?locale=en создается языковой стандарт без атрибута «страна» (задается только язык).Честно говоря, я не знаю, есть ли проблема - может, нет.2. Более серьезная проблема заключается в том, что он не работает ... я имею в виду, что он находится в нужном месте в цепочке фильтров (до защиты), он производит правильную локаль и устанавливает ее точно так же, как RequestContextFilter... но это просто не работает.

Я был бы очень рад, если бы кто-нибудь мог дать мне знать, как заставить i18n работать с пружинной защитой на основе моего примера или любого другого ...

Спасибо!

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: Я провел несколько экспериментов, и кажется, что экземпляр Locale из запроса как-то специфичен.

Посмотрите на этот код (изменил класс RequestContextFilter):

    @Override
protected void doFilterInternal(final HttpServletRequest request,
        final HttpServletResponse response, final FilterChain filterChain)
        throws ServletException, IOException {

    final ServletRequestAttributes attributes = new ServletRequestAttributes(
            request);
    final Locale l = Locale.GERMAN;
    final Locale l2 = request.getLocale();
    LocaleContextHolder.setLocale(l,
            this.threadContextInheritable);
    RequestContextHolder.setRequestAttributes(attributes,
            this.threadContextInheritable);
    if (logger.isDebugEnabled()) {
        logger.debug("Bound request context to thread: " + request);
    }
(...)

если для этого метода: LocaleContextHolder.setLocale(l, this.threadContextInheritable); я передаю язык 'l', он вообще не работает.Я имею в виду, что локаль не меняется, даже если она явно изменилась.С другой стороны, если я передам там Locale 'l2', который изменен на немецкий (в режиме отладки), он работает нормально!

Это означает, что по какой-то причине экземпляр Locale из request.getLocale() почему-то предпочтителен, возможно,что-то происходит позже в коде, который я не знаю / не знаю ...

Пожалуйста, дайте мне знать, как я должен использовать этот i18n вместе с соображениями безопасности, я дошел до того, что должен признать, чтоЯ понятия не имею, что происходит ...

- ==== - ====== - ====== - ======= - ====

ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ / ОТВЕТ (но все еще без особых вопросов) Благодаря Ральфу мне удалось исправить мою проблему.Раньше я шел в неправильном направлении, но сгенерированный руом проект подтолкнул меня вперед.Кажется, что я продолжал добавлять перехватчик неверным / не точным способом (предыдущий код):

<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
</bean>
<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="pl"/>
</bean>
<bean id="handlerMapping"
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
        <ref bean="localeChangeInterceptor" />
    </property>
</bean>

Таким образом перехватчик никогда не вызывался по какой-то причине.

После изменения перехватчика defto:

<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
</bean>
</mvc:interceptors>

<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="pl"/>
</bean>

<bean id="handlerMapping"
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>

... он начал нормально работать без каких-либо других изменений в security / web.xml.

Теперь проблема исчезла, но я не уверен, что случилось.Из того, что я понимаю во втором примере (тот, который работает), я сделал перехватчик "глобальным".Но почему перехватчик, определенный в первом примере, не работал?Любой намек?

Еще раз спасибо за помощь!Н.

Ответы [ 2 ]

1 голос
/ 12 декабря 2011
  1. После отправки запроса xxxxx? Locale = ru он создает Locale без атрибута "страна" (устанавливается только язык).

Это ожидаемое поведение. В Java есть какая-то иерархия. Язык более общий, чем страна.

Идея заключается в том, что вы можете иметь, например, текст в более распространенном языке, но некоторые единицы (например, валюта) в файлах, специфичных для страны.

@ см .: http://java.sun.com/developer/technicalArticles/Intl/IntlIntro/


  1. Более серьезная проблема в том, что она не работает ...

Он должен работать без какой-либо ручной реализации!

Вам необходимо зарегистрировать перехватчик локальных изменений и установить allowAll для страницы входа в систему.

<mvc:interceptors>         
     <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang"/>
</mvc:interceptors>

<http auto-config="true" use-expressions="true">
    <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
    <logout logout-url="/resources/j_spring_security_logout"/>

    <!-- Configure these elements to secure URIs in your application -->
    <intercept-url pattern="/login" access="permitAll" />
    <intercept-url pattern="/resources/**" access="permitAll" />
    <intercept-url pattern="/**" access="isAuthenticated()" />
</http>

Чтобы увидеть этот пример работающим, создайте проект roo с этим скриптом roo:

// Spring Roo 1.1.5.RELEASE [rev d3a68c3] log opened at 2011-12-13 09:32:23
project --topLevelPackage de.humanfork.test --projectName localtest --java 6
persistence setup --database H2_IN_MEMORY --provider HIBERNATE 
ent --class ~.domain.Stuff
field string --fieldName title
controller all --package ~.web
security setup
web mvc language --code de
web mvc language --code es

Тогда вы должны только изменить шаблоны intersept-url фильтров безопасности, как я показал выше (applicationContext-security.xml)!

Теперь у вас есть приложение, в котором пользователь может изменить свое локальное значение с помощью локального перехватчика изменений в приложении (когда пользователь вошел в систему), а также когда он не вошел в систему (на странице входа в систему)

0 голосов
/ 13 декабря 2011

У меня была похожая проблема с локализацией, когда я работал с приложением GWT. Проблема, которую я заметил, заключалась в том, что когда мы отображаем

<filter-mapping>
 <filter-name>localizationFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

к фильтру, четные запросы изображений направляются на фильтр. Эти запросы иногда пропускают параметр locale, и, следовательно, когда несколько запросов попадают в фильтр, параметр Locale отсутствует. Следовательно, как только я получил параметр locale, я поместил его в сеанс. Зарегистрируйте все заголовки запроса и значения, и вы можете найти основную причину.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...