简体   繁体   English

Spring security + LocaleResolver

[英]Spring security + LocaleResolver

i need to change locale settings after successful Authentication. 我需要在成功验证后更改区域设置。

LocaleResolver: 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;
       }

   }

Security: 安全:

     <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);
   }

}

When i try to set locale by RequestContextUtils i get NullPointer Exception. 当我尝试通过RequestContextUtils设置语言环境时,我得到NullPointer异常。

LocaleResolver is exposed in request context by DispatcherServlet , whereas AuthenticationSuccessHandler is fired before request enters DispatcherServlet (actually, request that fired SavedRequestAwareAuthenticationSuccessHandler never enters DispatcherServlet , because this handler performs a redirect). LocaleResolverDispatcherServlet请求上下文中公开,而AuthenticationSuccessHandler在请求进入DispatcherServlet之前被触发(实际上,发出SavedRequestAwareAuthenticationSuccessHandler请求永远不会进入DispatcherServlet ,因为此处理程序执行重定向)。

Thus, you cannot access LocaleResolver via RequestContextUtils in this case. 因此,你不能访问LocaleResolver通过RequestContextUtils在这种情况下。 You can try to inject LocaleResolver into your AuthenticationSuccessHandler explicitly, for example, with autowiring. 您可以尝试将LocaleResolver明确注入AuthenticationSuccessHandler ,例如,使用自动装配。

Even though the DispatcherServlet isn't normally reached when using Spring Security, you can add the RequestContextFilter BEFORE your security filter chain which exposes all the request attributes like the localeResolver. 尽管在使用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>

Even though this should make your example work. 即使这应该使你的例子工作。 For other people: another option is to use WebApplicationContextUtils.getWebApplicationContext(ServletContext) passing it the ServletContext that is available in the HttpServletRequest 对于其他人:另一种选择是使用WebApplicationContextUtils.getWebApplicationContext(ServletContext)传递HttpServletRequest中可用的ServletContext。

The solution from Kafkaesque is not complete. Kafkaesque的解决方案并不完整。

But even spring security documentation is wrong: 但即使是Spring安全文档也是错误的:

The LocaleContextHolder needs to be set up to contain the correct Locale before the filters are called. 在调用过滤器之前,需要将LocaleContextHolder设置为包含正确的Locale。 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. 您可以自己在过滤器中执行此操作(必须在web.xml中的Spring Security过滤器之前),或者您可以使用Spring的RequestContextFilter。

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

You can not use RequestContextFilter as this filter is not aware of any LocaleResolver inside your applicationContext. 您不能使用RequestContextFilter因为此过滤器不知道applicationContext中的任何LocaleResolver It just uses the Locale from request.getLocale() which is the Accept-Language Header. 它只使用来自request.getLocale()的Locale,它是Accept-Language Header。

If you want to use your own LocaleResolver in this filter you need to write your own: 如果您想在此过滤器中使用自己的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();
    }
}

and then configure your web.xml 然后配置您的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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM