Spring security + i18n = как заставить работать вместе?
Мой первый вопрос здесь, и я постараюсь быть конкретным. Я совсем новичок в 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
он создает Locale без атрибута "страна" (установлен только язык). Честно говоря, я не знаю, есть ли проблема - может, нет. 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>
Таким образом, перехватчик никогда не вызывался по какой-то причине.
После изменения перехватчика def на:
<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.
Теперь проблема исчезла, но я не уверен, что случилось. Из того, что я понимаю во втором примере (тот, который работает), я сделал перехватчик "глобальным". Но почему перехватчик, определенный в первом примере, не работал? Любой намек?
Еще раз спасибо за помощь! Н.