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 |