Servlet规范支持安全地访问 web 资源,只需要通过 web.xml 简单配置即可,其功能由服务器提供商实现,
web.xml
some name
*.jsp
*.do
GET
PUT
HEAD
TRACE
POST
DELETE
OPTIONS
tomcat
admin
NONE
admin page
/admin.jsp
admin
tomcat page
/tomcat.jsp
tomcat
FORM
/login.html
/error.html
tomcat
admin
安全规则:admin.jsp 只能由 admin 角色访问,tomcat.jsp 只能由 tomcat 角色访问,其它任意 *.jsp *.do 可由 admin 或 tomcat 角色访问。
认证方式:BASIC 是基础认证方式,由浏览器厂商实现的用户名和密码接收界面;FORM 是应用定制的用户名和密码接收页面;
角色声明:必需声明出所有用到的角色
JDBCRealm
DataSourceRealm
JNDIRealm
UserDatabaseRealm
MemoryRealm
JAASRealm
CombinedRealm
LockOutRealm
每种不同的 Realm 采用了不同的 用户名和密码存储和使用方式,tomcat默认使用的是 UserDatabaseRealm。
create table users (
user_name varchar(15) not null primary key,
user_pass varchar(15) not null
);
create table user_roles (
user_name varchar(15) not null,
role_name varchar(15) not null,
primary key (user_name, role_name)
);
insert into users ( user_name , user_pass ) values ( 'admin','admin')
insert into users ( user_name , user_pass ) values ( 'tomcat','admin')
insert into user_roles values ( 'admin','admin')
insert into user_roles values ( 'tomcat','tomcat')
2.继续添加安全域配置(这里会使用jndi引用上面注册的数据源资源):
package jaas;
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import java.security.Principal;
import java.util.Map;
public class MyLoginModule implements LoginModule {
// username and password
private String username;
private char[] password;
// the authentication status
private boolean userPwdSucceeded = false;
private boolean commitSucceeded = false;
// user's Principal
private Principal userPrincipal;
// initial state
private Subject subject;
private CallbackHandler callbackHandler;
/**
* Initialize this LoginModule
.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map sharedState,
Map options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
}
/**
* Authenticate the user by prompting for a user name and password.
*/
public boolean login() throws LoginException {
// prompt for a user name and password
if (callbackHandler == null)
throw new LoginException("Error: no CallbackHandler available " +
"to garner authentication information from the user");
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("user name");
callbacks[1] = new PasswordCallback("password", false);
// callbacks[2] = new TextOutputCallback(TextOutputCallback.INFORMATION, "hello, just a msg!");
// callbacks[3] = new TextOutputCallback(TextOutputCallback.WARNING, "just warn you!");
try {
callbackHandler.handle(callbacks);
NameCallback nameCallback = (NameCallback) callbacks[0];
PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];
username = nameCallback.getName();
char[] tmpPassword = passwordCallback.getPassword();
passwordCallback.clearPassword();// clean password in memory space
if (tmpPassword == null) {
tmpPassword = new char[0];// treat a NULL password as an empty password
}
password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
} catch (Exception e) {
e.printStackTrace();
}
// verify the username/password
// boolean usernameCorrect = false;
// if (username.equals("user")) usernameCorrect = true;
//
// if (usernameCorrect &&
// password.length == 3 &&
// password[0] == 'p' &&
// password[1] == 'w' &&
// password[2] == 'd') {
//
// userPwdSucceeded = true;
// } else {
// userPwdSucceeded = false;
// cleanUserAndPwdData();
// if (!usernameCorrect) {
// throw new FailedLoginException("User Name Incorrect");
// } else {
// throw new FailedLoginException("Password Incorrect");
// }
// }
// return userPwdSucceeded;
userPwdSucceeded=true;
return true;
}
public boolean commit() throws LoginException {
if (!userPwdSucceeded) return false;
// add a Principal (authenticated identity) to the Subject
userPrincipal = new SamplePrincipal(username);
subject.getPrincipals().add(userPrincipal);
// for tomcat jaas realm
if (username.equals("admin")) {
subject.getPrincipals().add(new SampleRolePrincipal("admin"));
} else if (username.equals("tomcat")) {
subject.getPrincipals().add(new SampleRolePrincipal("tomcat"));
}
// in any case, clean out state
cleanUserAndPwdData();
return commitSucceeded = true;
}
public boolean abort() throws LoginException {
if (!userPwdSucceeded) return false;
if (commitSucceeded) {
logout();
} else {
cleanState();
}
return true;
}
public boolean logout() throws LoginException {
subject.getPrincipals().remove(userPrincipal);
cleanState();
userPwdSucceeded = commitSucceeded;
return true;
}
private void cleanState() {
userPwdSucceeded = false;
cleanUserAndPwdData();
userPrincipal = null;
}
private void cleanUserAndPwdData() {
username = null;
if (password != null) {
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
}
}
}
package jaas;
import java.security.Principal;
public class SamplePrincipal implements Principal {
private String name;
public SamplePrincipal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
package jaas;
public class SampleRolePrincipal extends SamplePrincipal {
public SampleRolePrincipal(String name) {
super(name);
}
}