在中Tomcat实现JAAS

这两天学习了一下JAAS,并遇到了一个Tomcat的bug,这里记录下来。


[url=http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html]http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html[/url]


这是sun的JAAS developer guide。


开始学习JAAS对于几个概念很混淆,我的习惯是先理大框架,如果大概念不清晰不轻易往下看。找来找去,在callan的博客找到一篇[url=http://callan.iteye.com/blog/158392]http://callan.iteye.com/blog/158392[/url]
,这里的几个例子举得非常贴切


[quote]理解这些类和接口的关系我给个生动的比方:一个军事学校,入学的时候校方(LoginModule)根据学生(Subject)的入学通知来确定其合法性,这个过程交由某工作人员(CallbackHandler)执行,(CallbackHandler)确认后,(LoginModule)给不同(Subject)根据其身份发给相关的证件(Principal),有了该证件就可以访问对应的资源,(Subject)根据自己的(Principal)的级别可以使用和访问学校不同资源。


一个(Subject)的(Principal)如果是士官级,那么可以访问的资源就相对少些,如果是将军级那就多些。当然一个(Subject)可以拥有多个(Principal)。


通过分析我们会发现,JAAS采用的也是身份检查+权限分配模式。因此JAAS的应用也分成两个部分:(1)认证;(2)授权。过程是先认证后根据身份来授权(有歧视的嫌疑的东东,本人可是反歧视人士)。 [/quote]
-----------------------------赞叹的分割线--------------------------------------
由于最近在玩tomcat,所以作了几个实验都是基于tomcat的。[url]http://tomcat.apache.org/tomcat-6.0-doc/realm-howto.html[/url]给出了几个例子,我试了JDBCRealm和MemoryRealm都没问题。但在试org.apache.catalina.realm.JAASRealm时遇到了问题,tomcat总是报
[quote]2009-11-11 13:40:10 org.apache.catalina.realm.JAASRealm parseClassNames
严重: Class tt.User not found! Class not added.
2009-11-11 13:40:10 org.apache.catalina.realm.JAASRealm parseClassNames
严重: Class tt.Role not found! Class not added.[/quote]
这里 User和Role是extends Principal的POJO.页面也会登录不成功转到403 error
查了一下发现这是tomcat的一个bug [url]https://issues.apache.org/bugzilla/show_bug.cgi?id=44084[/url]。 根本原因是以前启动tomcat时JAASReaml不去验证UserClassName和RoleClassName,于是一哥们就报了个bug[url]https://issues.apache.org/bugzilla/show_bug.cgi?id=40150[/url]。修40150的哥们去Class.forName了一把就把状态fix了,结果他没注意所用的ClassLoader(估计UT时用的是Tomcat/lib里面的类),然后Jetspeed的开发者就发现他们的自定义Principal找不到了。
以上不是重点,重点是[url]https://sec1.woopra.com/docs/changelog.html[/url]说这个bug在6.0.16中就真正fix了。但我看了一下我的tomcat正是6.0.16啊!又去下了个6.0.20还是有这个问题。
我的解决是,在eclipse的server配置中open luanch configuration->Classpath->User Entries中单独加入这两个类。试了试好了。
没时间去看tomcat这块代码,感觉上这是个没修好的bug?
-----------------------------郁闷的分割线--------------------------------------
几点感想
1) Subject,Principal这两个名字起的超烂
2)LoginModule.login先构造一个Callback(UserNameCallback,PasswordCallback)数组,再由CallbackHandler.handle()去负责获取具体的UserName,Password。看看这里的代码

 for (Callback cb : cbs) {
if (cb instanceof NameCallback) {
NameCallback nc = (NameCallback) cb;
nc.setName(userName);
}
if (cb instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) cb;
pc.setPassword(password.toCharArray());
}
}

强转啊强转,bad smell啊bad smell
另外这里感觉像template method更多些。既然CallbackHandler用到强转,说明它已经和LoginModule绑在一起了,既然不能decouple,干脆把Callback去掉,写成这样

class LoginModule{
abstract void readLoginInfo();
}

当然...这样似乎不好重用,而且显得不是很酷。不过到底有多少人会用到DNA验证呢?就算用到多写两句也不会死人吧。这样换来和直觉相一致的设计是否值得?
-----------------------------完结的分割线--------------------------------------
我没有自己去写JAAS Realm,看架势Sun的设计是一个subject能带着不同类型的principal,而org.apache.catalina.realm.JAASRealm只有一个Role,如果我希望有多种维度的权限(比如User同时属于不同的Company和Location)怎么办?自己实现一个JAASRealm吗?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值