Spring security + LocaleResolver

时间:2011-11-06 10:03:50

标签: java spring-mvc spring-security locale

我需要在成功验证后更改区域设置。

和LocaleResolver:

    <bean id="localeChangeInterceptor"
    class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="lng" />
    </bean>

   <bean id="localeResolver"
     class="web.MyLocaleResolver">
   </bean>

   public class MyLocaleResolver extends AbstractLocaleResolver {

   private Locale default = Locale.ENGLISH;

       @Override
       public Locale resolveLocale(HttpServletRequest hsr) {
           return this.default;
       }

       @Override
       public void setLocale(HttpServletRequest hsr, HttpServletResponse hsr1,         Locale default) {
           this.default = default;
       }

   }

安全性:

     <form-login login-page="/login" 
          authentication-success-handler- ref="MySuccessAuthHandler"/>
     <beans:bean id="MySuccessAuthHandler" class="web.MySuccessfulAuthenticationHandler">
         <beans:property name="defaultTargetUrl" value="/index.htm"></beans:property>
     </beans:bean>

public class MySuccessfulAuthenticationHandler extends  SavedRequestAwareAuthenticationSuccessHandler  {
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws ServletException, IOException {

        super.onAuthenticationSuccess(request, response, authentication);
        RequestContextUtils.getLocaleResolver(request).setLocale(request, response, Locale.ENGLISH);
   }

}

当我尝试按RequestContextUtils设置区域设置时,我得到NullPointer异常。

3 个答案:

答案 0 :(得分:9)

LocaleResolver在请求上下文中由DispatcherServlet公开,而AuthenticationSuccessHandler在请求输入DispatcherServlet之前被触发(实际上,被解雇的请求SavedRequestAwareAuthenticationSuccessHandler永远不会进入{ {1}},因为此处理程序执行重定向。)

因此,在这种情况下,您无法通过DispatcherServlet访问LocaleResolver。您可以尝试明确地将RequestContextUtils注入LocaleResolver,例如,使用自动装配。

答案 1 :(得分:2)

尽管在使用Spring Security时通常无法访问DispatcherServlet,但您可以在安全过滤器链之前添加RequestContextFilter,它会公开所有请求属性,例如localeResolver。

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

即使这应该让你的例子有用。对于其他人:另一种选择是使用WebApplicationContextUtils.getWebApplicationContext(ServletContext)传递HttpServletRequest中可用的ServletContext

答案 2 :(得分:1)

Kafkaesque的解决方案尚未完成。

但即使是Spring安全文档也是错误的:

  

需要将LocaleContextHolder设置为包含正确的   调用过滤器之前的区域设置。你可以这样做   过滤自己(必须在Spring Security过滤器之前)   web.xml)或者您可以使用Spring的RequestContextFilter。

请参阅https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#localization

您无法使用RequestContextFilter,因为此过滤器不知道您的applicationContext中的任何LocaleResolver。它只使用request.getLocale()中的Accept-Language标题的区域设置。

如果您想在此过滤器中使用自己的LocaleResolver,则需要自己编写:

@Component
public class LocaleRequestContextFilter extends OncePerRequestFilter
{
    // basiert auf RequestContextFilter
    @Inject
    private LocaleResolver      localeResolver;

    @Override
    protected void doFilterInternal ( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain ) throws ServletException, IOException
    {
        ServletRequestAttributes attributes = new ServletRequestAttributes(request, response);
        initContextHolders(request, attributes);
        try
        {
            filterChain.doFilter(request, response);
        }
        finally
        {
            resetContextHolders();
            attributes.requestCompleted();
        }
    }

    private void initContextHolders ( HttpServletRequest request, ServletRequestAttributes requestAttributes )
    {
        LocaleContextHolder.setLocaleContext(buildLocaleContext(request));
        RequestContextHolder.setRequestAttributes(requestAttributes, false);
    }

    private LocaleContext buildLocaleContext ( final HttpServletRequest request )
    {
        request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, localeResolver);
        if (this.localeResolver instanceof LocaleContextResolver)
        {
            return ( (LocaleContextResolver) this.localeResolver ).resolveLocaleContext(request);
        }
        else
        {
            return new LocaleContext()
            {
                @Override
                public Locale getLocale ( )
                {
                    return localeResolver.resolveLocale(request);
                }
            };
        }
    }

    private void resetContextHolders ( )
    {
        LocaleContextHolder.resetLocaleContext();
        RequestContextHolder.resetRequestAttributes();
    }
}

然后配置您的web.xml

<filter>
    <filter-name>localeRequestContextFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>localeRequestContextFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>