Spring security + LocaleResolver - PullRequest
       12

Spring security + LocaleResolver

3 голосов
/ 06 ноября 2011

Мне нужно изменить настройки языка после успешной аутентификации.

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 ]

9 голосов
/ 06 ноября 2011

LocaleResolver предоставляется в контексте запроса с помощью DispatcherServlet, тогда как AuthenticationSuccessHandler запускается до того, как запрос входит DispatcherServlet (на самом деле, запрос, который сгенерировал SavedRequestAwareAuthenticationSuccessHandler, никогда не входит в DispatcherServlet, потому что этот обработчик выполняет перенаправление).

Таким образом, вы не можете получить доступ к LocaleResolver через RequestContextUtils в этом случае.Вы можете попытаться внедрить LocaleResolver в ваш AuthenticationSuccessHandler явно, например, с помощью автоматической разводки.

2 голосов
/ 16 июня 2015

Даже если DispatcherServlet обычно не достигается при использовании Spring Security, вы можете добавить RequestContextFilter ПЕРЕД вашей цепочкой фильтров безопасности, которая предоставляет все атрибуты запроса, например localeResolver.сделай свой пример работоспособнымДля других людей: другой вариант - использовать WebApplicationContextUtils.getWebApplicationContext(ServletContext), передав ему ServletContext, который доступен в HttpServletRequest

1 голос
/ 13 сентября 2017

Решение от Kafkaesque не является полным.

Но даже весенняя документация по безопасности неверна:

Необходимо настроить LocaleContextHolder так, чтобы он содержал правильный Locale, прежде чем фильтры будутназывается.Вы можете сделать это самостоятельно в фильтре (который должен предшествовать фильтрам Spring Security в web.xml) или использовать RequestContextFilter Spring.

см. https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#localization

Выне может использовать RequestContextFilter, так как этот фильтр не знает ни одного LocaleResolver внутри вашего applicationContext.Он просто использует Locale из request.getLocale(), который является Accept-Language Header.

Если вы хотите использовать свой собственный 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>
...