JAAS:Java Authentication and Authorization Service,提供了认证和授权框架。
本例是认证的实现,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
;
}
;
此文件定义了一个“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
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
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.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();
}
}