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

时间:2011-12-12 17:32:12

标签: spring spring-mvc localization internationalization spring-security

我在这里的第一个问题,我将尝试具体。我对Spring很陌生,我试图创建一个非常简单的预订系统(但这实际上并不重要)。重要的是我正在创建一些基本模板,然后我将通过真实的网页填写。应用程序适用于hibernate,mysql,我还设置了i18n和spring security。问题在于我无法改变我的语言环境。唯一有效的是改变默认值。 首先,我浏览了Web A LOT,我发现使用i18n和弹簧安全性通常更复杂。我发现的是我需要额外的过滤器:

<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。我调试了它,它似乎不是为了这个目的而创建的(这就是我需要的)。 这取自春季样本&#34;联系人&#34;但是在这个例子中,我找不到任何实际上以改变语言为目标的代码。效果是它根本不起作用。它总是尝试将语言环境更改为我的默认语言环境。好消息是,如果在调试模式下,我手动将区域设置更改为其他一个,它工作得很好,所以我心里充满希望......; - )

然后我通过创建我们自己的过滤器找到了其他方法。我所做的是合并找到的例子(不要记得作者)以及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();
    }
}

}

如您所见,解析了请求参数区域设置并设置了区域设置。有两个问题: 1.发送请求xxxxx?locale=en后,它会创建没有&#34; country&#34;的区域设置。属性(仅设置语言)。说实话,我不知道它是否有任何问题 - 也许不是。 2.更严重的问题是它不起作用......我的意思是它在过滤器链中的正确位置(在安全性之前),它产生正确的区域设置并且将它设置为exackly像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); 我通过现场直播&#39; l&#39;它根本不起作用。我的意思是即使你明确改变了语言环境也没有改变。 另一方面,如果我通过Locale&#39; l2&#39;修改为德语(在调试模式下)它工作正常!

这意味着由于某种原因,来自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进行任何其他更改。

现在问题已经消失,但我不确定发生了什么。根据我在第二个例子(有效的那个)中的理解,我制作了拦截器&#34; global&#34;。但是为什么在第一个例子中定义的拦截器不起作用?任何提示?

再次感谢您的帮助! Ñ

2 个答案:

答案 0 :(得分:1)

  
      
  1. 发送请求xxxxx?locale = en后,它会创建没有“country”属性的Locale(仅设置语言)。
  2.   

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

背后的想法是,你可以在更常见的语言中使用文本,但在国家特定文件中有一些单位(如货币)。

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


  
      
  1. 更严重的问题是它不起作用......
  2.   

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

您需要注册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)!

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

答案 1 :(得分:0)

当我使用GWT应用程序时,我遇到了与Localization类似的问题。我注意到的问题是,当我们映射

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

到过滤器,偶数图像请求被路由到过滤器。这些请求有时会遗漏locale参数,因此当多个请求命中过滤器时,Locale参数不会。因此,只要我收到locale参数,就会将其放入会话中。记录所有请求标头和值,您可能会找到根本原因。