Acegi中文登录帐号问题的解决方案

                                                             Acegi中文登录帐号问题的解决方案

Acegi登陆使用中文帐号名登陆时会抛出异常,下面我贴出的JSP页面上抛出的错误信息(只贴出有分析价值的一部分):

root cause

 
 

 

分析异常的原因,应该是底层的ServerCookie试图增加一个值为张三的cookie导致的异常,(cookiename肯定不能为中文,这个“张三”应该为value值,但value应该可以是中文的(我用的GBK编码,查看ServerCookie.java好象是用了isToken方法来验证这个cookievalue)),另外这个cookieacegi框架中如何传递给ServerCookie的很让人困惑。

我按cookie单词查找了acegi(1.0.5版本)sourcecode,没有发现acegi中有增加中文cookie的地方,以下是跟cookie相关的类:

SavedRequest.java,SavedRequestAwareWrapper.java,RememberMeServices.java,TokenBasedRememberMeServices.java,我的acegi配置文件中没有配置rememberme相关的过滤器,所以cookie应该和rememberme类没关系,下面是我配置的acegi的过滤器:

/**=httpSessionContextIntegrationFilter,casProcessingFilter,logoutFilter,concurrentSessionFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor

我在org.acegisecurity.util.FilterChainProxy类的VirtualFilterChain子类中删除session,cookie,

发现java.lang.IllegalArgumentException: 张三 的异常仍然存在,于是我怀疑到是否认证之后,org.apache.tomcat.util.http.ServerCookie是从request.getUserPrincipal().getName()中获取登陆名试图加入到cookie中的,request.getUserPrincipal().getName()返回的是张三,即中文登陆帐号,此值的赋值方式也非常奇怪,在org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter.java中,有一句:

                 request = (HttpServletRequest) constructor.newInstance(new Object[] {request, portResolver});

 

在此句之前使用request.getUserPrincipal().getName()会抛出异常,因为getUserPrincipal()是空的,在执行了constructor.newInstance之后再运行request.getUserPrincipal().getName(),发现此句能获得登陆帐号“张三”,不知道这个newInstance是什么原理,怎么会自动地填充了principal信息(看来我的servletAPI原理了解的比较有限)

一个简单的让acegi支持中文帐号登陆的方式就是在org.acegisecurity.ui.webapp.AuthenticationProcessingFilter中将从页面获得的登陆id进行替换,替换为中文对应的英文id,这种方式经测试是可行的,而且绕过了上面提到的cookie的问题,

具体实现就是首先获得页面的中文登陆帐号,然后从数据库的登陆帐号表中找到这个中文帐号(可以使用登陆帐号表的用户名称作为中文帐号),然后找到中文帐号对应的英文帐号,例如根据“张三”找到”zhangsan”,经过测试后,这种方式完全可行!参考下面AuthenticationProcessingFilter更改后的代码:

 

    String username = obtainUsername(request);

    String password = obtainPassword(request);

     //使用替代方案,如果不支持中文登陆帐号,可建立一个中文帐号-英文帐号对照表,根据中文帐号替换为英文帐号,按英文帐号登录

        String userid = "";

        try

        {

        if(username!=null&&username.trim().length()>0)

        {

             userid = ServiceLocator.getDBSupportService().findSingleValueBySql("select user_id from eas_login_user where user_name='"+username+"'", null).toString();

        }

        }

        catch(Exception ex)

        {

        System.out.println("查询用户错误!");

        }

        if(userid==null)userid="";

       

        if (username == null) {

            username = "";

        }

 

        if (password == null) {

            password = "";

        }

        username=userid; //将中文登陆帐号替换为英文帐号

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

AuthenticationProcessingFilter是获取页面登录用户帐号和口令的入口点,所以在这里替换后,后面的生成AuthenticationPrincipal信息都按照替换后的英文登陆帐号处理。

 

这种替换帐号的方式固然可行,不过cookie的问题还有很有继续研究的必要,这有助于我们从更深的层次了解servlet容器的原理。

 

                                                                          王保政

Msn:baozhengw999@hotmail.com

QQ:29803446

Email:baozhengw@netease.com

 

 

 

 

转载于:https://www.cnblogs.com/ajuanabc/archive/2008/05/14/2463015.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值