JAAS认证的可pluggable特性,保证了JAVA程序的独立性,独立于底层的身份认证技术。并且新的认证技术插拔也不需要更新JAVA应用。
特定的身份认证implementation是在运行阶段被确认。具体的implementation配置在登录配置文件中。
import javax.security.auth.Subject;
import javax.security.auth.login.*;
/**
* 这个例子尝试认证一个用户,并报告认证是否成功
*/
public class DemoClient {
public static void main(String[] args) {
/*
* 实例化LoginContext
* "Sample"是JAAS登录配置文件中的条目。指定了(一个或多个)实现了LoginModule接口的类。
* MyCallbackHandler可以让CallbackHandler访问到所需的用户信息,比如用户名、密码
*/
LoginContext lc = null;
try {
lc = new LoginContext("Sample",
new MyCallbackHandler());
} catch (LoginException le) {
System.err.println("Cannot create LoginContext. "
+ le.getMessage());
System.exit(-1);
} catch (SecurityException se) {
System.err.println("Cannot create LoginContext. "
+ se.getMessage());
System.exit(-1);
}
// 用户3次尝试通过认证
int i;
for (i = 0; i < 3; i++) {
try {
/*
* 尝试认证
* LoginContext 实例化一个新的空javax.security.auth.Subject对象 (它代表了经过认证的用户或服务)。
* LoginContext 构造配置中的 LoginModule,并使用Subject对象和MyCallbackHandler对它完成初始化。
* login方法开始调用 LoginModule 中的方法进行登录和认证。
* LoginModule 通过MyCallbackHandler获得用户名和密码,并验证是否有效
* 如果认证通过,LoginModule 使用 Principal 填充 Subject 用以代表用户
*/
lc.login();
// 如果没有异常发生,说明认证成功
break;
} catch (LoginException le) {
System.err.println("Authentication failed:");
System.err.println(" " + le.getMessage());
try {
Thread.currentThread().sleep(3000);
} catch (Exception e) {
// ignore
}
}
}
// did they fail three times?
if (i == 3) {
System.out.println("Sorry");
System.exit(-1);
}
Subject subject = lc.getSubject();
System.out.println("Authentication succeeded!" + subject);
}
}
运行:
java -Djava.security.auth.login.config==Demo.conf jaas.DemoClient