本例是认证的实现,JAAS定义了可插拔的认证机制,使认证逻辑独立开来,可通过修改配置文件切换认证模块。
官方参考:
http://java.sun.com/products/archive/jaas/
http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html
security.pdf
一、配置文件及设置
1. 配置文件(假设为D:/jaas.conf):
Sample{
com.fastunit.samples.jaas.SampleLoginModule required debug = false ;
} ;
com.fastunit.samples.jaas.SampleLoginModule required debug = false ;
} ;
此文件定义了一个“Sample”验证模块,使用SampleLoginModule来进行验证。
2. 启用配置文件:
-Djava.security.auth.login.config=D:/jaas.conf
二、客户端调用
import
javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
public class LoginManager {
public static boolean login(HttpServletRequest request) {
try {
String username = request.getParameter( " username " );
String password = request.getParameter( " password " );
// 此处指定了使用配置文件的“Sample”验证模块,对应的实现类为SampleLoginModule
LoginContext lc = new LoginContext( " Sample " , new SampleCallbackHandler(
username, password));
lc.login(); // 如果验证失败会抛出异常
return true ;
} catch (LoginException e) {
e.printStackTrace();
return false ;
} catch (SecurityException e) {
e.printStackTrace();
return false ;
}
}
}
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
public class LoginManager {
public static boolean login(HttpServletRequest request) {
try {
String username = request.getParameter( " username " );
String password = request.getParameter( " password " );
// 此处指定了使用配置文件的“Sample”验证模块,对应的实现类为SampleLoginModule
LoginContext lc = new LoginContext( " Sample " , new SampleCallbackHandler(
username, password));
lc.login(); // 如果验证失败会抛出异常
return true ;
} catch (LoginException e) {
e.printStackTrace();
return false ;
} catch (SecurityException e) {
e.printStackTrace();
return false ;
}
}
}
import
java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class SampleCallbackHandler implements CallbackHandler {
private String username;
private String password;
public SampleCallbackHandler( final String username, final String password) {
this .username = username;
this .password = password;
}
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());
}
}
}
}
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class SampleCallbackHandler implements CallbackHandler {
private String username;
private String password;
public SampleCallbackHandler( final String username, final String password) {
this .username = username;
this .password = password;
}
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());
}
}
}
}
三、验证实现
import
java.io.IOException;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
public class SampleLoginModule implements LoginModule {
private boolean isAuthenticated = false ;
private CallbackHandler callbackHandler;
private Subject subject;
private SamplePrincipal principal;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this .subject = subject;
this .callbackHandler = callbackHandler;
}
public boolean login() throws LoginException {
try {
NameCallback nameCallback = new NameCallback( " username " );
PasswordCallback passwordCallback = new PasswordCallback( " password " ,
false );
final Callback[] calls = new Callback[] { nameCallback, passwordCallback };
// 获取用户数据
callbackHandler.handle(calls);
String username = nameCallback.getName();
String password = String.valueOf(passwordCallback.getPassword());
// TODO 验证,如:查询数据库、LDAP。。。
if ( true ) { // 验证通过
principal = new SamplePrincipal(username);
isAuthenticated = true ;
} else {
throw new LoginException( " user or password is wrong " );
}
} catch (IOException e) {
throw new LoginException( " no such user " );
} catch (UnsupportedCallbackException e) {
throw new LoginException( " login failure " );
}
return isAuthenticated;
}
/**
* 验证后的处理,在Subject中加入用户对象
*/
public boolean commit() throws LoginException {
if (isAuthenticated) {
subject.getPrincipals().add(principal);
} else {
throw new LoginException( " Authentication failure " );
}
return isAuthenticated;
}
public boolean abort() throws LoginException {
return false ;
}
public boolean logout() throws LoginException {
subject.getPrincipals().remove(principal);
principal = null ;
return true ;
}
}
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
public class SampleLoginModule implements LoginModule {
private boolean isAuthenticated = false ;
private CallbackHandler callbackHandler;
private Subject subject;
private SamplePrincipal principal;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this .subject = subject;
this .callbackHandler = callbackHandler;
}
public boolean login() throws LoginException {
try {
NameCallback nameCallback = new NameCallback( " username " );
PasswordCallback passwordCallback = new PasswordCallback( " password " ,
false );
final Callback[] calls = new Callback[] { nameCallback, passwordCallback };
// 获取用户数据
callbackHandler.handle(calls);
String username = nameCallback.getName();
String password = String.valueOf(passwordCallback.getPassword());
// TODO 验证,如:查询数据库、LDAP。。。
if ( true ) { // 验证通过
principal = new SamplePrincipal(username);
isAuthenticated = true ;
} else {
throw new LoginException( " user or password is wrong " );
}
} catch (IOException e) {
throw new LoginException( " no such user " );
} catch (UnsupportedCallbackException e) {
throw new LoginException( " login failure " );
}
return isAuthenticated;
}
/**
* 验证后的处理,在Subject中加入用户对象
*/
public boolean commit() throws LoginException {
if (isAuthenticated) {
subject.getPrincipals().add(principal);
} else {
throw new LoginException( " Authentication failure " );
}
return isAuthenticated;
}
public boolean abort() throws LoginException {
return false ;
}
public boolean logout() throws LoginException {
subject.getPrincipals().remove(principal);
principal = null ;
return true ;
}
}
import java.security.Principal;
public final class SamplePrincipal implements Principal {
private String name;
public SamplePrincipal(String name) {
this .name = name;
}
public String getName() {
return name;
}
public boolean equals(Object o) {
return (o instanceof SamplePrincipal)
&& this .name.equalsIgnoreCase(((SamplePrincipal) o).name);
}
public int hashCode() {
return name.toUpperCase().hashCode();
}
}