3

我正在使用 Spring Security 3.1.0 和 Spring MVC 3.1.1。我希望能够根据 URL 更改语言环境,即:

http://localhost:8080/abc?lang=fr

现在,这在“正常”情况下有效,即从一个页面到另一个页面但是,在我的应用程序中,如果我从一个非安全页面转到一个安全页面,它首先命中的是我的登录页面,由 Spring Security BEFORE 提供它击中了我想要的页面。

这是正常的 Spring Security 行为(拦截安全资源),因此这种行为没有问题。

问题在于,当我到达安全页面时,语言环境并没有改变!它保留为默认语言环境。即 ..e lang=fr 没有被解析出来。

我已经在应用程序上下文文件中定义了 dispatcher-servlet.xml 和外部的语言环境相关 bean,以执行以下操作:

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

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" p:defaultLocale="en" />

我还尝试拆分上述 2 个 bean,在 app-context 配置中只有localResolver 。

我已经对此进行了大量研究,基本上,我知道我需要手动更改语言环境。

甚至 Spring Security 3.1.0 的 Spring Docs 都说您需要自己的“过滤器”,或者您可以使用 RequestContextFilter。但是,RequestContextFilter 不会解析查询字符串中的语言环境参数。

Spring Security relies on Spring's localization support in order to actually lookup   
the appropriate message. In order for this to work, you have to make sure that the 
locale from the incoming request is stored in Spring's 
org.springframework.context.i18n.LocaleContextHolder. Spring MVC's DispatcherServlet 
does this for your application automatically, but since Spring Security's filters are 
invoked before this, the LocaleContextHolder needs to be set up to contain the correct 
Locale before the filters are called.  You can either do this in a filter yourself 
(which must come before the Spring Security filters in web.xml) or you can use 
Spring's RequestContextFilter.

我想在请求到达控制器之前拦截它,所以我编写了自己的过滤器。

基于其他人所做的,我的解决方案是自动装配 LocaleResolver。当 tomcat 启动时,它在我的日志中显示“localeResolver”已被自动连接(否则应用程序将在那里失败)但是在运行时,localeResolver 为 NULL。

同样,有帖子说要在应用程序上下文中定义 LocaleResolver ......我已经这样做了,但是当请求发生时我仍然最终得到一个空的 LocaleResolver 。

有任何想法吗??非常感激。

ps 我定义的过滤器在 Spring Security 过滤器之前。我可以调试它,它首先命中它,然后由于 LocaleResolver 上的 NPE 而死掉。

欣赏这个,谢谢。

4

1 回答 1

4

您是否在 web.xml 中定义了过滤器?如果是这样,那么过滤器类不是由 Spring 实例化的,而是由 servlet 容器实例化的。Spring 无法自动装配它不知道的内容。

这里的一般解决方案是将<filter-class>web.xml 中的声明为org.springframework.web.filter.DelegatingFilterProxy并将 指向targetBeanName上下文中的 bean,例如:

<filter>
    <filter-name>My Locale Filter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>myLocaleFilter</param-value>
    </init-param>
</filter>

在您的 Spring 上下文中,<bean id="myLocaleFilter">应该指向您的 Filter 类。

您可能还会发现自定义过滤器类扩展GenericFilterBean而不是Filter直接实现接口很方便。

于 2012-04-24T15:44:10.157 回答