Spring security + i18n = 如何让它一起工作?

标签 spring spring-mvc localization internationalization spring-security

我的第一个问题在这里,我会尽量具体。我对 Spring 很陌生,我正在尝试创建非常简单的预订系统(但这实际上并不重要)。重要的是我正在创建一些基本模板,然后我将用真实的网页填写。应用程序适用于 hibernate、mysql,我还设置了 i18n 和 spring 安全性。问题是我不能改变我的语言环境。唯一有效的是更改默认值。
首先,我浏览了很多 Web,我发现将 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 .我调试了它,它似乎不是为此目的而创建的(这就是我需要的)。
这是从 spring 示例“联系人”中获取的,但是在此示例中,我找不到任何实际针对更改语言的代码。结果是它根本不起作用。它总是尝试将语言环境更改为我的默认语言环境。好消息是,如果在 Debug模式下,我手动将 locale-to-set 更改为其他区域设置,它运行良好,所以我心中充满希望......;-)

然后我找到了其他方法 - 通过创建我们自己的过滤器。我所做的是将找到的示例(不要记住作者)与方式合并在一起 RequestContextFilter被 build 。毕竟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 与 spring-security 一起工作,我会非常高兴...

谢谢!

附加信息:
我做了一些实验,似乎请求中的 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'(在 Debug模式下),它工作正常!

这意味着出于某种原因,来自 request.getLocale() 的 Locale 实例以某种方式受到青睐,也许稍后在代码中发生了一些我不知道/不明白的事情......

请让我知道我应该如何将这个 i18n 与安全性一起使用,因为我已经到了必须承认我不知道发生了什么的地步......

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

最终解决方案/答案 (但仍然没有什么问题)
感谢拉尔夫,我设法解决了我的问题。以前我走错了方向,但 roo 生成的项目插入了我前进。
似乎我一直以错误/不准确的方式添加拦截器(以前的代码):
<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 进行任何其他更改。

现在问题消失了,但我不确定发生了什么。根据我在第二个示例(有效的示例)中的理解,我将拦截器设为“全局”。但是为什么第一个例子中定义的拦截器不起作用?任何提示?

再次感谢您的帮助!
N。

最佳答案

  1. After sending request xxxxx?locale=en it creates Locale without "country" attribute (only language is set).


这是预期的行为。在java中有某种层次结构。
语言比国家更普遍。

背后的想法是,例如,您可以在更常见的语言中使用文本,但在国家/地区特定文件中使用某些单位(如货币)。

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

  1. The more serious problem is that it doesn't work...


它应该在没有任何手工实现的情况下工作!

需要注册Local Change Interceptor,登录页面需要设置permitAll。
<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)!

现在您有一个应用程序,用户可以通过应用程序中的本地更改拦截器(当用户登录时)以及未登录时(在登录页面中)更改其本地

关于Spring security + i18n = 如何让它一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8478321/

相关文章:

ruby-on-rails - globalize3 和 easy_globalize3_accessors 验证

localization - 通过 Typoscript 添加对 TYPO3 扩展的翻译

java - 如何比较各种缓存框架的速度?

java - intellij 错误地说没有为 Autowiring 的存储库找到类型的 bean

java - spring 3、hibernate、dbcp 和 derby 连接问题

java - 嵌套异常是 java.lang.IllegalStateException : Cannot convert value of type [java. lang.String] 到所需类型

ios - 以编程方式更改应用程序语言以在 iOS 中进行本地化

rest - 返回类型为标记接口(interface)时使用 Jackson 进行多态序列化

java - Controller 未在 spring-mvc 应用程序中调用

java - Tomcat 使用 Spring MVC 返回 404 页面;未到达 Controller