Spring Security Spring安全+ i18n =如何让它一起工作?

k2fxgqgv  于 2023-03-30  发布在  Spring
关注(0)|答案(3)|浏览(144)

我的第一个问题,我会尽量具体。我是相当新的Spring,我试图创建相当简单的预订系统(但这实际上并不重要).重要的是,我创建一些基本的模板,然后我会填写真实的的网页.应用程序在hibernate,mysql,我还设置了i18 n和spring安全。问题是我不能改变我的语言环境。唯一有效的是改变默认的。首先,我浏览了很多Web,我发现使用i18 n和Spring Security 比通常更复杂。我发现我需要额外的过滤器:

<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,我调试了一下,好像不是为了这个目的创建的(这就是我需要的)。这是从spring示例“contacts”中提取的,但是在这个例子中,我找不到任何实际针对更改语言的代码。结果是它根本不起作用。它总是试图将locale更改为我的默认语言。好消息是,如果在调试模式下,我手动将本地设置更改为其他设置,它工作得很好,所以我感到希望在我的心中…;- )
然后我找到了一些其他的方法-通过创建我们自己的过滤器。我所做的是将找到的示例(不记得作者)与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();
    }
}

}

正如你所看到的,请求参数locale被解析并设置了locale。有2个问题:1.在发送请求xxxxx?locale=en后,它创建了没有“country”属性的Locale(只设置了语言).说实话我不知道这是否有问题-也许没有.2.更严重的问题是它不起作用...我的意思是它在过滤器链中的正确位置(在安全设置之前),它会产生正确的locale,并以与RequestContextFilter相同的方式设置它...但它根本不起作用。
如果有人能让我知道如何让i18 n在spring-security中工作,我会非常高兴,基于我给出的示例或任何其他示例。
谢谢!
其他信息:我做了一些实验,看起来request中的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);我传递locale 'l'它根本不起作用。我的意思是,即使显式更改,locale也不会更改。另一方面,如果我传递Locale 'l2',它被修改为德语(在调试模式下),它可以正常工作!
这意味着由于某种原因,request.getLocale()中的Locale示例在某种程度上受到了青睐,也许代码中稍后发生了一些我不知道/不理解的事情...
请让我知道我应该如何使用这个i18 n与安全的原因,我到了一点,我必须承认,我不知道发生了什么事...
-====-======-======--=======-====

最终解决方案/答案(但仍然有一点问题)感谢Ralph,我设法解决了我的问题。以前我走错了方向,但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进行任何其他更改。
现在问题解决了,但是我不确定发生了什么。从我在第二个例子中的理解(工作的那个),我使拦截器“全局”。但是为什么在第一个例子中定义的拦截器不工作?任何提示?
再次感谢您的帮助!

lmyy7pcs

lmyy7pcs1#

1.在发送请求xxxxx?locale=en之后,它创建了没有“country”属性的Locale(只设置了语言)。
这是预期的行为。在java中有某种层次结构。语言比国家更通用。
背后的想法是,你可以有例如文本在更常见的语言,但一些单位(如货币)在国家特定的文件。
@见:http://java.sun.com/developer/technicalArticles/Intl/IntlIntro/
1.更严重的问题是它不起作用…
它应该工作没有任何手工制作的实施!
需要注册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)!
现在您有了一个应用程序,用户可以通过应用程序中的本地更改拦截器更改其本地(当用户登录时)以及当他未登录时(在登录页面中)

lg40wkob

lg40wkob2#

我在使用GWT应用程序时遇到过类似的本地化问题。

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

到过滤器,甚至图像请求被路由到过滤器.这些请求有时会忽略locale参数,因此当多个请求命中过滤器时,Locale参数不会.因此,一旦我收到locale参数,我就把它放在一个会话中.记录所有请求头和值,你可能会找到根本原因.

z9zf31ra

z9zf31ra3#

使用Spring 6,这对我来说很有用:
Spring安全不允许使用 *?lang= parameter。我不得不将以下内容添加到过滤器链中:

.requestMatchers(req ->
          req.getParameterMap().containsKey("lang")).permitAll()

我创建了配置类并在其中定义了beans:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
    public MessageSource messageSource(){
        ReloadableResourceBundleMessageSource messageSource =
                new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:" + myClassPath);
        return messageSource;
    }

@Bean
    public LocaleChangeInterceptor localeChangeInterceptor(){
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return localeChangeInterceptor;
    }
}

@Bean
    public LocaleResolver localeResolver(){
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        return localeResolver;
    }

@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }

然后我可以使用Thymeleaf从任何端点发出请求:

<li><a class="dropdown-item" th:href="@{''(lang=en)}">English</a></li>

相关问题