這期先介紹有關 Authentication 的部分, JAAS 提供了 PAM ( Pluggable Authentication Module ) 的模塊, 可 以通過標準的 API 建立屬于自己的 LoginModule, 根據 stackable 原理, 進而相關相關的身份驗證程序, 達到 SSO ( Single Sign-On ) 的 目的.
SECTION 02 JAAS 中幾個比較常見的 classes
本節詳細解說請參考 http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html
普通對象
- Subject
- Principals
- Credentials
- LoginContext
- LoginModule
- CallbackHandler
- Callback
- Policy
- AuthPermission
- PrivateCredentialPermission
SECTION 03 Tagish.net 的 LoginModules
現在地點 http://free.tagish.net/jaas/
最新版本 1.0.3
目前 tagish.net 提供了幾種 LoginModules, 包含了
- com.tagish.auth.DBLogin
- com.tagish.auth.FileLogin
- com.tagish.auth.win32.NTSystemLogin
JAASLogin { com.tagish.auth.DBLogin required dbDriver="sun.jdbc.odbc.JdbcOdbcDriver" dbURL="jdbc:odbc:DBLogin"; };將 Principal 設置為 com.tagish.auth.TypedPrincipal ( 如果是 NTSystemLogin 則設置為 com.tagish.auth.win32.NTPrincipal ). 接著, 你的數據庫需要一些表,

分別在數據庫內設置完成. 當你啟動你的程序的時候, 你需要在 classpath 中設置相關的 JDBC Driver, 讓 SecurityManager 參考 login.config, 去調用 DBLogin api, 取得合法或不合法的狀態.
SECTION 04 關于 PAM stack
Login2 { sample.SampleLoginModule required; com.sun.security.auth.module.NTLoginModule sufficient; com.foo.SmartCard requisite debug=true; com.foo.Kerberos optional debug=true; };假如我們用 Login2 的這種登陸stack, 可以設置 required, sufficient, requisite, optional 四種狀態.
- required : 驗證必須成功, 但是不論成功或失敗都繼續執行下面的登陸模塊, 執行所有之后才丟出驗證失敗.
- requisite : 驗證必須成功, 但是失敗就馬上回去不做其他驗證, 必須成功才繼續執行下面的登陸模塊.
- sufficient : 驗證可以不要成功, 但是成功了就馬上回去不做其他驗證, 失敗可以繼續執行其他的登陸模塊.
- optional : 驗證可以不要成功, 但是不論成功或失敗都繼續執行下面的登陸模塊.
不論成功或失敗都會執行 com.sun.security.auth.module.NTLoginModule,
如果 NTLoginModule 驗證成功, 因為是 sufficient, 系統就認定這個人是合法的使用者,
當 NTLoginModule 驗證失敗, 就會進行 com.foo.SmartCard 的驗證,
如果 SmartCard 驗證失敗, 就直接宣告你不是合法的使用者,
如果 SmartCard 驗證成功, 就繼續到 Kerberos 的驗證模塊,
因為 Kerberos 是屬于 optional, 所以根本對身份驗證的結果沒有影響.
Login2 驗證的各種狀況列表 | |||||||||
---|---|---|---|---|---|---|---|---|---|
SampleLoginModule | required | pass | pass | pass | pass | fail | fail | fail | fail |
NTLoginModule | sufficient | pass | fail | fail | fail | pass | fail | fail | fail |
SmartCard | requisite | * | pass | pass | fail | * | pass | pass | fail |
Kerberos | optional | * | pass | fail | * | * | pass | fail | * |
Overall Authentication | pass | pass | pass | fail | fail | fail | fail | fail |
SECTION 05 套用 Tomcat 4/5 的 JAASRealm
建立 login.config 放到 $CATALINA_HOME/conf/ 之中, 范例采用 MS SQLServer, jTds.sf.net 的 jdbc driver
JAASLoginModule { com.tagish.auth.DBLogin required dbDriver="net.sourceforge.jtds.jdbc.Driver" dbURL="jdbc:jtds:sqlserver://localhost:1433/JAASDB" dbUser="sa" dbPassword="sa_password" userTable="Users" roleTable="Roles" roleMapTable="RoleMap"; };在 tomcat 啟動腳本中加入
JAVA_OPTS=-Djava.security.auth.login.config==C:\tomcat4\conf\login.config 并且修改 server.xml, 讓 appName 去對應 login.config 中的 JAASLoginModule, 以及設置 User/Group 相關的 Principal
<Realm className="org.apache.catalina.realm.JAASRealm" appName="JAASLoginModule" userClassNames="com.tagish.auth.TypedPrincipal" roleClassNames="com.tagish.auth.TypedPrincipal" debug="99"/>最后設置 web.xml 中的 login-config 以及要保護的數據, 例如
<security-constraint> <web-resource-collection> <web-resource-name>User Protected</web-resource-name> <url-pattern>/protected/*</url-pattern> <url-pattern>/protected.jsp</url-pattern> </web-resource-collection> <auth-constraint> <role-name>user</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> <realm-name>MyJAASRealm</realm-name> </login-config>SECTION 06 結論
JAAS 除了在一般 Desktop Application 應用之外, 對 J2EE 支持將會是一個主流, 無論是 JSR 196: Java Authentication Service Provider Interface for Containers 還 是 JSR 115: Java Authorization Contract for Containers ( 已經納入 J2EE 1.4 之中 ) 都是對 container 提供者要求標準的 provider 界面, 因此, 將來開發相關的程序最好能夠遵循 JAAS, 在異構平臺的整合 上, 才能具備完整的相容性.