Spring Security + i18n =如何使其协同工作? [英] Spring security + i18n = how to make it work together?

查看:62
本文介绍了Spring Security + i18n =如何使其协同工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里的第一个问题,我将尽量具体.我对Spring还是很陌生,我正在尝试创建一个非常简单的预订系统(但这实际上无关紧要).重要的是,我正在创建一些基本模板,然后将这些模板填充到真实的网页中.应用程序可以在hibernate,mysql上运行,我还可以设置i18n和spring安全性.问题是我无法更改语言环境.唯一有效的方法是更改​​默认值. 首先,我浏览了Web A LOT,然后发现与弹簧安全性一起使用i18n通常比通常更复杂.我发现我需要附加过滤器:

My first question here and i'll try to be specific. I am quite new to Spring and i'm trying to create quite simple reservation system (but this actually doesn't matter). What matters is that I am creating some basic template which i will then fill in by real webpages. Application works on hibernate,mysql, I also setup i18n and spring security. The poblem is that I cannot change my locale. The only thing which works is changing the default one. First I browed Web A LOT and I found out that usage a i18n together with spring security is more complicated that usually. What i found out is that i need to have additional filter:

<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.我调试了它,似乎它不是出于这种目的而创建的(这就是我所需要的). 这取自春季示例联系人",但是在此示例中,我找不到更改语言时实际针对的任何代码.结果是它根本不起作用.它总是尝试将语言环境更改为我的默认语言环境.好消息是,如果我在调试模式下手动将语言环境设置更改为其他语言环境,则它可以正常工作,因此我心中充满希望...;-)

What I found out is that this filter is indeed processed before the security one however it does not parse the request in a form: http://someserver.com/bla/home?locale=en. I debugged it and it seems that it's not created for such purpose (and that's what I need). This is taken from spring sample "contacts" however in this example I couldn't find any code that was actually targeting in changing the language. The effect is that it simply doesn't work. It always tries to change locale to my default one. The good news is that if in debug mode I manualy changed the locale-to-set to some other one it worked fine so i felt hope in my heart... ;-)

然后我找到了其他方法-通过创建我们自己的过滤器.我所做的是将找到的示例(不要记住作者)与创建RequestContextFilter的方式合并在一起.毕竟RequestContextFilter正常工作-只是请不要解析我的请求.那是新过滤器的代码:

Then i've found some other way - by creating our own filter. What i did is to merge found example (don't remeber author) together with the way how RequestContextFilter is created. After all the RequestContextFilter works fine - just donest parse my requests. That's code of the new filter:

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

}

如您所见,解析了请求参数语言环境并设置了语言环境.有两个问题: 1.发送请求xxxxx?locale=en后,它将创建不带国家/地区"属性的语言环境(仅设置语言).老实说,我不知道这是否有问题-也许不是. 2.更严重的问题是它不起作用...我的意思是它在筛选器链中的正确位置(在安全性之前),它会产生正确的语言环境并以与RequestContextFilter相同的方式进行设置...但是它根本不起作用.

As you can see the request paramter locale is parsed and the locale is set. There are 2 problems: 1. After sending request xxxxx?locale=en it creates Locale without "country" attribute (only language is set). To be honest I don't know if it's any problem - maybe not. 2. The more serious problem is that it doesn't work... i mean it's in the right place in the filter chain (before the security one), it produces right locale and sets it in exackly the same way like RequestContextFilter... but it simply doesnt work.

如果有人可以根据我给出的示例或任何其他信息,让我知道如何使i18n在弹簧安全性方面工作,我将感到非常高兴.

I would be very happy if someone could let me know how to make i18n work with spring-security basing on my example given or any other...

谢谢!

其他信息: 我做了一些实验,看来请求中的Locale实例在某种程度上是特定的.

ADDITIONAL INFO: I made some experiments and it seems that the Locale instance from request is somehow specific.

看下面的代码(修改了RequestContextFilter类):

Look at this code (modified the RequestContextFilter class):

    @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); 我通过语言环境"l",它根本不起作用.我的意思是即使您明确更改了语言环境也不会更改. 另一方面,如果我在此处传递的语言环境"l2"被修改为德语(在调试模式下),则可以正常工作!

if to this method: LocaleContextHolder.setLocale(l, this.threadContextInheritable); I pass locale 'l' it doesn't work at all. I mean the locale doesn't change even thou it's explicitly changed. On the other hand if I pass there Locale 'l2' which is modified to german (in debug mode) it works fine!

这意味着出于某种原因,request.getLocale()中的Locale实例受到青睐,也许稍后代码中发生了我不知道/不了解的事情……

This means that for some reason the Locale instance from request.getLocale() is somehow favored, maybe something is going on later on in the code which I don't know/understant...

请让我知道该如何将i18n与安全原因一起使用,以至于我必须承认我不知道发生了什么...

Please let me know how should I use this i18n together with security cause I got to the point where I must admit that I have no idea what's going on...

-====-======-=====-=======-====

-====-======-======--=======-====

最终解决方案/答案(但仍然有一点疑问) 感谢拉尔夫,我设法解决了我的问题.以前,我走错了方向,但是项目清单生成的项目推动了我前进. 看来我一直以错误/不正确的方式添加拦截器(先前的代码):

FINAL SOLUTION/ANSWER (but still with little question) Thanks to Ralph I managed to fix my issue. Previously I was going the wrong direction but the roo generated project pushed me forward. It seems that I kept adding the interceptor in a wrong/not accurate way (previous code):

<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>

这样,由于某种原因,从未调用过拦截器.

This way the interceptor was never invoked for some reason.

将拦截器def更改为:

After changing interceptor def to:

<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进行任何其他更改.

... it started to work fine without any other changes to security/web.xml.

现在问题解决了,但是我不确定发生了什么.根据我在第二个示例(有效的示例)中所了解的,我将拦截器设置为全局".但是,为什么在第一个示例中定义的拦截器不起作用?有提示吗?

Now the problem is gone however I am not sure what happened. From what i understand in the second example (the one that works) I made the interceptor "global". But why the interceptor definded in the first example didn't work? Any hint?

再次感谢您的帮助! N.

Thanks again for help! N.

推荐答案

  1. 在发送请求xxxxx?locale = en后,它会创建没有国家/地区"属性的语言环境(仅设置了语言).

这是预期的行为.在Java中,存在某种层次结构. 语言比国家更笼统.

It is the expected behaviour. In java there is some kind of hierarchy. The language is more general then the country.

其背后的想法是,例如,您可以在更通用的语言中使用文本,但在特定于国家/地区的文件中可以包含某些单位(例如货币).

The idea behind is that you can have for example the text in the more common languge but some units (like currency) in the country specific files.

@see: http://java.sun.com/developer/technicalArticles/Intl/IntlIntro/

  1. 更严重的问题是它不起作用...

它应该无需任何手工实现即可工作!

It should work without any hand made implementation!

您需要注册本地更改拦截器,并需要为登录页面设置permitAll.

You need to register the Local Change Interceptor, and need to set permitAll for the login page.

<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项目:

To see this example running, create a roo project with that roo script:

// 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)!

Then you must only change the security filters intersept-url patterns like I have shown above (applicationContext-security.xml)!

现在有了一个应用程序,用户可以通过应用程序中的本地更改拦截器(在用户登录时)以及未登录时(在登录页面中)更改其本地

Now you have a application where the user can change its local via the local change interceptor in the application (when the user is logged in) as well as when he is not logged in (in the login page)

这篇关于Spring Security + i18n =如何使其协同工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆