Author charles @ chinaxp.org
以XForum来说明如何使用JAAS做用户验证
JAAS的简单流程:
初始化一个generic的LoginContext
Call LoginContext.login()验证用户
如果成功,获得一个经过代表当前用户的Subject object,Subject中含有用户数据
不成功得到一个LoginException
开发过程:
1.建立一个Implements java.secuirty.principal的User object,因为在Subject中的数据必须是
Pricipal,所以我们建议个User principal,这个principal中目前只保存用户名信息
2.建立一个客户化的LoginModule,这个Class 需要Implement javax.security.auth.spi.LoginModule;
由于XForum使用Mysql数据库作为用户数据的数据源,因此我们建立一个Database LoginModule.
LoginModule中的所有methods都是由一个generic 的LoginContext来调用的.
/*
* A dependent Database login module for JAAS
* and create the connection
*
* @author Charles Huang
* @since JDK1.4
* @version $Id: DataBaseLoginModule.java,v 1.1 2002/09/10 02:05:48 charles Exp $
*/
public class DataBaseLoginModule implements LoginModule{
/**
*
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this.subject = subject;
//CallbackHandler是JAAS用来在用户的application
//比如说jsp或swing application的用户界面和LoginModule之间传递数据的
//Data Holder
this.callbackHandler = callbackHandler;
}
public boolean login() throws LoginException {
try{
//利用CallBack objects
final Callback[] calls= new Callback[2];
calls[0]=new NameCallback("name");
calls[1]=new PasswordCallback("Password",false);
//从 CallbackHandler里获得用户
//输入的用户名和密码,
callbackHandler.handle(calls);
// 查询数据库,比较密码
}catch( AccountNotFoundException ){
throw LoginExceptionm("No such User");
}
isAuthenticated = true;
return isAuthenticated;
}
/**
* 这里做验证后的处理,在XForum如果成功,在Subject中加入用户名.一个Subject代表一个
*被验证 的
*用户.Subject中可以包含较丰富的数据,如用户名,role等数据,会被web application引用
*/
public boolean commit() throws LoginException {
if ( isAuthenticated ){
subject.getPrincipals().add( new User( username ) );
//TODO: Put in role information later
}else{
throw new LoginException("Authentication fails");
}
return isAuthenticated;
}
......
}
3.建立一个客户化的CallbackHandler用来在用户的application和LoginModule之间传递数据.因为web
application不回直接调用LoginModul.这里使用了visitor pattern.XForum中的CallbackHandler只传
递两个数据:用户名和密码
public class SimpleCallbackHandler implements CallbackHandler{
private String username;
private String password;
public SimpleCallbackHandler( final String username, final String password) {
this.username = username;
this.password = password;
}
//在LoginModule的login method中,LoginModule 调用这个handle()并pass in 两个
// CallBack Objects,着两个callback objects被populated
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for( int index = 0; index < callbacks.length; index++ ){
if(callbacks[ index ] instanceof NameCallback){
NameCallback ncb = (NameCallback)callbacks[ index ];
ncb.setName(username);
}
if(callbacks[ index ] instanceof PasswordCallback){
PasswordCallback pcb = (PasswordCallback)callbacks[ index ];
pcb.setPassword(password.toCharArray());
}
}
}
}
4.在web application中用JAAS严正用户,在XForum中,这是在LogonAction
......
// let the LoginContext instantiate a new Subject,其中userName and password
//从HttpRequest中获得,并利用SimpleCallbackHandler传递给LoginModule
LoginContext lc = new LoginContext("XForumLogin",
new SimpleCallbackHandler( userName, password ) );
// LoginContext 调用LoginModule的login()来验证用户
lc.login();
//获得一个经过验证的Subject object,这个Subject中包含一个User object
subject = lc.getSubject();
......
5.建里一个LoginModule的Configuration file.JAAS中的LoginContext会看这个文件,并动态的Load这
个class和产生一个LoginModule的Instance用来验证用户,在XForum中的configuration file为
XForumLogin.config
XForumLogin{
org.redsoft.forum.security.DataBaseLoginModule required debug=true;
};
6.修改{java_home}/jre/lib/security/java.security来告诉JAAS 配置文件XForumLogin.config在那
里
#
# Default login configuration file
#
login.config.url.1=file:E:/jakarta-tomcat-4.0.2/webapps/forum/WEB-INF/XForumLogin.config
重起Tomcat,done