前提
请先看,JAAS 认证部分: http://blog.csdn.net/conquer0715/article/details/78204889
配置文件和源码
jaas.config
/** 登录配置 **/
Sample {
jaas.MyLoginModule required debug=true;
};
jaas.policy
grant codeBase "file:/home/conquer/mine/work_space/idea/Eden/jse/target/classes/*" {
//permission java.security.AllPermission;
permission javax.security.auth.AuthPermission "createLoginContext.Sample";
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.AuthPermission "doAsPrivileged";
};
// JAAS 授权,授权给指定的用户或身份
grant codeBase "file:/home/conquer/mine/work_space/idea/Eden/jse/target/classes/*",
Principal jaas.SamplePrincipal "user" {
permission java.util.PropertyPermission "java.home", "read";
permission java.util.PropertyPermission "user.home", "read";
permission java.io.FilePermission "foo.txt", "read";
};
MyLoginModule.java
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 <code>LoginModule</code>.
*/
public void initialize(Subject subject,
CallbackHandler callbackHandler,
Map<java.lang.String, ?> sharedState,
Map<java.lang.String, ?> 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[4];
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;
}
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);
// 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;
}
}
}
MyCallbackHandler.java
package jaas;
import javax.security.auth.callback.*;
import java.io.IOException;
public class MyCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) {// display the message according to the specified type
TextOutputCallback toc = (TextOutputCallback) callbacks[i];
switch (toc.getMessageType()) {
case TextOutputCallback.INFORMATION:
System.out.println(toc.getMessage());
break;
case TextOutputCallback.ERROR:
System.err.println("ERROR: " + toc.getMessage());
break;
case TextOutputCallback.WARNING:
System.err.println("WARNING: " + toc.getMessage());
break;
default:
throw new IOException("Unsupported message type: " + toc.getMessageType());
}
} else if (callbacks[i] instanceof NameCallback) {// prompt the user for a username
NameCallback nc = (NameCallback) callbacks[i];
String name = "user";// TODO 这里可以实现为从控制台允许用户输入等方式接收用户参数。。。
nc.setName(name);
} else if (callbacks[i] instanceof PasswordCallback) {// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback) callbacks[i];
String pwd = "pwd";// TODO 这里可以实现为从控制台允许用户输入等方式接收用户参数。。。
pc.setPassword(pwd.toCharArray());
} else {
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback");
}
}
}
}
SamplePrincipal.java
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;
}
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
if (!(o instanceof SamplePrincipal))
return false;
SamplePrincipal that = (SamplePrincipal) o;
if (this.getName().equals(that.getName()))
return true;
return false;
}
public int hashCode() {
return name.hashCode();
}
}
MyPrivilegedAction.java
package jaas;
import java.io.File;
import java.security.PrivilegedAction;
public class MyPrivilegedAction implements PrivilegedAction {
public Object run() {
System.out.println("\nYour java.home property value is: "
+ System.getProperty("java.home"));
System.out.println("\nYour user.home property value is: "
+ System.getProperty("user.home"));
File f = new File("foo.txt");
System.out.print("\nfoo.txt does ");
if (!f.exists())
System.out.print("not ");
System.out.println("exist in the current working directory.");
return null;
}
}
测试代码:
package jaas;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.Principal;
import java.security.PrivilegedAction;
public class Main {
public static void main(String[] args) throws LoginException {
// 配置文件中查找 Sample 名字的 LoginModule,并指定 CallbackHandler
LoginContext lc = new LoginContext("Sample", new MyCallbackHandler());
try {
lc.login();
Subject subject = lc.getSubject();
// System.out.println(subject);
System.out.println("Authentication succeeded!");
// 下面是 JAAS “授权” 示例代码
Subject mySubject = lc.getSubject();
System.out.println("Authenticated user has the following Principals:");
for (Principal principal : mySubject.getPrincipals()) {
System.out.println("\t" + principal.toString());
}
System.out.println("User has " +
mySubject.getPublicCredentials().size() +
" Public Credential(s)");
// now try to execute the MyPrivilegedAction as the authenticated Subject
PrivilegedAction action = new MyPrivilegedAction();
Subject.doAsPrivileged(mySubject, action, null);
} catch (LoginException e) {
System.err.println("Authentication failed:" + e.getMessage());
e.printStackTrace();
}
}
}
说明
其它类的说明请看 JAAS 认证部分: http://blog.csdn.net/conquer0715/article/details/78204889 文章,
MyPrivilegedAction:是我们需要验证权限的类,它实现了 java.security.PrivilegedAction 安全接口。
javax.security.auth.Subject#getPrincipals()方法可以获取到当前登录模块内所有已经成功验证的身份。
javax.security.auth.Subject#getPublicCredentials()方法可以获取到当前的所有证书。
运行代码,修改 policy 权限文件可以发现,只有经过授权的用户才可以运行MyPrivilegedAction里面的代码。