方案
Acegi登陆使用中文帐号名登陆时会抛出异常,下面我贴出的JSP页面上抛出的错误信息(只贴出有分析价值的一部分):
root cause
java.lang.IllegalArgumentException: 张三
org.apache.tomcat.util.http.ServerCookie.maybeQuote(ServerCookie.java:276)
org.apache.tomcat.util.http.ServerCookie.appendCookieValue(ServerCookie.java:209)
org.apache.coyote.tomcat5.CoyoteResponse.addCookie(CoyoteResponse.java:950)
org.apache.coyote.tomcat5.CoyoteResponseFacade.addCookie(CoyoteResponseFacade.java:291)
javax.servlet.http.HttpServletResponseWrapper.addCookie(HttpServletResponseWrapper.java:102)
分析异常的原因,应该是底层的ServerCookie试图增加一个值为张三的cookie导致的异常,(cookie的name肯定不能为中文,这个“张三”应该为value值,但value应该可以是中文的(我用的GBK编码,查看ServerCookie.java好象是用了isToken方法来验证这个cookie的value值)),另外这个cookie是acegi框架中如何传递给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是获取页面登录用户帐号和口令的入口点,所以在这里替换后,后面的生成Authentication和Principal信息都按照替换后的英文登陆帐号处理。
这种替换帐号的方式固然可行,不过cookie的问题还有很有继续研究的必要,这有助于我们从更深的层次了解servlet容器的原理。
分享到:
相关推荐
Spring Security 是一款基于 Spring 框架的安全插件,提供了完整的安全性解决方案,包括身份认证(Authentication)、授权(Authorization)以及会话管理(Session Management)等功能。Spring Security 的设计目标是为...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...
JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...