JAAS样例

经过几天研究,终于跑起来了第一个JAAS例子。把代码贴上来,免得以后忘了。

 

MyCallbackHandler.java(处理用户输入)

package com.pingan.jaas.tutorial;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.util.Arrays;

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.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

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) {
				// 根据指定的类型显示信息
				TextOutputCallback toc = (TextOutputCallback) callbacks[i];
				switch (toc.getMessageType()) {
				case TextOutputCallback.INFORMATION:
					System.out.println(toc.getMessage());
					break;
				case TextOutputCallback.ERROR:
					System.out.println("ERROR: " + toc.getMessage());
					break;
				case TextOutputCallback.WARNING:
					System.out.println("WARNING: " + toc.getMessage());
					break;
				default:
					throw new IOException("Unsupported message type: "
							+ toc.getMessageType());
				}
			} else if (callbacks[i] instanceof NameCallback) {
				// 如果命令行没有提供用户名,提示用户输入用户名
				NameCallback nc = (NameCallback) callbacks[i];

				System.err.print(nc.getPrompt());
				System.err.flush();
				nc
						.setName((new BufferedReader(new InputStreamReader(
								System.in))).readLine());
			} else if (callbacks[i] instanceof PasswordCallback) {
				// prompt the user for a password
				PasswordCallback pc = (PasswordCallback) callbacks[i];

				System.err.print(pc.getPrompt());
				System.err.flush();
				pc.setPassword(readPassword(System.in));
			} else {
				throw new UnsupportedCallbackException(callbacks[i],
						"Unrecognized Callback");
			}
		}

	}

	private char[] readPassword(InputStream in) throws IOException {
		char[] lineBuffer;
		char[] buf;

		buf = lineBuffer = new char[128];

		int room = buf.length;
		int offset = 0;
		int c;

		loop: while (true) {
			switch (c = in.read()) {
			case -1:
			case '\n':
				break loop;

			case '\r':
				int c2 = in.read();
				if ((c2 != '\n') && (c2 != -1)) {
					if (!(in instanceof PushbackInputStream)) {
						in = new PushbackInputStream(in);
					}
					((PushbackInputStream) in).unread(c2);
				} else
					break loop;

			default:
				if (--room < 0) {
					buf = new char[offset + 128];
					room = buf.length - offset - 1;
					System.arraycopy(lineBuffer, 0, buf, 0, offset);
					Arrays.fill(lineBuffer, ' ');
					lineBuffer = buf;
				}
				buf[offset++] = (char) c;
				break;
			}
		}

		if (offset == 0) {
			return null;
		}

		char[] ret = new char[offset];
		System.arraycopy(buf, 0, ret, 0, offset);
		Arrays.fill(buf, ' ');

		return ret;
	}

}

 

SampleAcn.java(客户端)

 

package com.pingan.jaas.tutorial;

import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

public class SampleAcn {
	public static void main(String[] args) {
		LoginContext lc = null;
		try {
			lc = new LoginContext("test5", 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 retryTimes = 3;
		int i;
		for (i = 0; i < retryTimes; i++) {
			try {
				// attempt authentication
				lc.login();
				// if we return with no exception,
				// authentication succeeded
				break;
			} catch (LoginException le) {
				System.err.println("Authentication failed:");
				System.err.println("  " + le.getMessage());
				try {
					Thread.sleep(3000);
				} catch (Exception e) {
					// ignore
				}
			}
		}

		// did they fail three times?
		if (i == retryTimes) {
			System.out.println("Sorry");
			System.exit(-1);
		}

		System.out.println("Authentication succeeded!");

	}
}

 

 

 

SamplePrincipal.java(自定义Principal类)

package com.pingan.jaas.tutorial;

import java.security.Principal;

public class SamplePrincipal implements Principal, java.io.Serializable {
	private static final long serialVersionUID = -5974294088673749367L;
	private String name;

	public SamplePrincipal(String name) {
		if (name == null)
			throw new NullPointerException("illegal null input");
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public String toString() {
		return ("SamplePrincipal:  " + 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();
	}

}

 

 

 

SampleLoginModule.java(自定义登录模块)

package com.pingan.jaas.tutorial;

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.FailedLoginException;
import javax.security.auth.login.LoginException;

import examples.util.LogHelper;

public class SampleLoginModule {
	// initial state
	private Subject subject;
	private CallbackHandler callbackHandler;
	private Map sharedState;
	private Map options;

	// configurable option
	private boolean debug = false;

	// the authentication status
	private boolean succeeded = false;
	private boolean commitSucceeded = false;

	// username and password
	private String username;
	private char[] password;

	// testUser's SamplePrincipal
	private SamplePrincipal userPrincipal;

	public void initialize(Subject subject, CallbackHandler callbackHandler,
			Map sharedState, Map options) {

		this.subject = subject;
		this.callbackHandler = callbackHandler;
		this.sharedState = sharedState;
		this.options = options;

		// initialize any configured options
		debug = "true".equalsIgnoreCase((String) options.get("debug"));
	}

	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);

		try {
			callbackHandler.handle(callbacks);
			username = ((NameCallback) callbacks[0]).getName();
			char[] tmpPassword = ((PasswordCallback) callbacks[1])
					.getPassword();
			if (tmpPassword == null) {
				// treat a NULL password as an empty password
				tmpPassword = new char[0];
			}
			password = new char[tmpPassword.length];
			System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
			((PasswordCallback) callbacks[1]).clearPassword();

		} catch (java.io.IOException ioe) {
			throw new LoginException(ioe.toString());
		} catch (UnsupportedCallbackException uce) {
			throw new LoginException("Error: " + uce.getCallback().toString()
					+ " not available to garner authentication information "
					+ "from the user");
		}

		// print debugging information
		if (debug) {
			System.out.println("\t\t[SampleLoginModule] "
					+ "user entered user name: " + username);
			System.out.print("\t\t[SampleLoginModule] "
					+ "user entered password: ");
			for (int i = 0; i < password.length; i++)
				System.out.print(password[i]);
			System.out.println();
		}

		// 校验用户名和密码(用户名为testUser,密码为testPassword,区分大小写)
		boolean usernameCorrect = false;
		boolean passwordCorrect = false;
		if (username.equals("testUser"))
			usernameCorrect = true;
		if (usernameCorrect && password.length == 12 && password[0] == 't'
				&& password[1] == 'e' && password[2] == 's'
				&& password[3] == 't' && password[4] == 'P'
				&& password[5] == 'a' && password[6] == 's'
				&& password[7] == 's' && password[8] == 'w'
				&& password[9] == 'o' && password[10] == 'r'
				&& password[11] == 'd') {

			// authentication succeeded!!!
			passwordCorrect = true;
			if (debug)
				System.out.println("\t\t[SampleLoginModule] "
						+ "authentication succeeded");
			succeeded = true;
			return true;
		} else {

			// authentication failed -- clean out state
			if (debug)
				System.out.println("\t\t[SampleLoginModule] "
						+ "authentication failed");
			succeeded = false;
			username = null;
			for (int i = 0; i < password.length; i++)
				password[i] = ' ';
			password = null;
			if (!usernameCorrect) {
				throw new FailedLoginException("User Name Incorrect");
			} else {
				throw new FailedLoginException("Password Incorrect");
			}
		}
	}

	public boolean commit() throws LoginException {
		LogHelper.log2Console("succeeded=" + succeeded);
		if (succeeded == false) {
			return false;
		} else {
			// add a Principal (authenticated identity)
			// to the Subject

			// assume the user we authenticated is the SamplePrincipal
			userPrincipal = new SamplePrincipal(username);
			if (!subject.getPrincipals().contains(userPrincipal))
				subject.getPrincipals().add(userPrincipal);

			if (debug) {
				System.out.println("\t\t[SampleLoginModule] "
						+ "added SamplePrincipal to Subject");
			}

			// in any case, clean out state
			username = null;
			for (int i = 0; i < password.length; i++)
				password[i] = ' ';
			password = null;

			commitSucceeded = true;
			return true;
		}
	}

	public boolean abort() throws LoginException {
		LogHelper.log2Console("succeeded=" + succeeded);
		if (succeeded == false) {
			return false;
		} else if (succeeded == true && commitSucceeded == false) {
			// login succeeded but overall authentication failed
			succeeded = false;
			username = null;
			if (password != null) {
				for (int i = 0; i < password.length; i++)
					password[i] = ' ';
				password = null;
			}
			userPrincipal = null;
		} else {
			// overall authentication succeeded and commit succeeded,
			// but someone else's commit failed
			logout();
		}
		return true;
	}

	public boolean logout() throws LoginException {
		subject.getPrincipals().remove(userPrincipal);
		succeeded = false;
		succeeded = commitSucceeded;
		username = null;
		if (password != null) {
			for (int i = 0; i < password.length; i++)
				password[i] = ' ';
			password = null;
		}
		userPrincipal = null;
		return true;
	}

}

 

该类没有实现javax.security.auth.spi.LoginModule接口,似乎也可以运行。为简单起见,代码里面用户名固定为testUser,密码固定为testPassword。 

 

 

 

还有一个MyLoginModule类,跟SampleLoginModule类是一样的,只是修改了硬编码的用户名和密码,便于测试。

 

Sample_jaas.config(JAAS配置文件)

Sample {
   com.pingan.jaas.tutorial.SampleLoginModule required debug=true;
};
Sample2 {
   com.pingan.jaas.tutorial.MyLoginModule required debug=true;
};
all_required {
	com.pingan.jaas.tutorial.SampleLoginModule required debug=true;
	com.pingan.jaas.tutorial.MyLoginModule required debug=true;	
};
test3 {
	com.pingan.jaas.tutorial.SampleLoginModule required debug=true;
	com.pingan.jaas.tutorial.MyLoginModule Sufficient debug=true;
};
test4 {
	com.pingan.jaas.tutorial.MyLoginModule Sufficient debug=true;
	com.pingan.jaas.tutorial.SampleLoginModule required debug=true;
};
test5 {
	com.pingan.jaas.tutorial.MyLoginModule Optional debug=true;
	com.pingan.jaas.tutorial.SampleLoginModule required debug=true;
};

 

 

 

 

为了测试不同情况,配置了多个组合,具体使用哪个组合,在上文中客户端代码指定。

 

 编译后运行客户端,需要在命令行指定JAAS配置文件位置,参考命令行如下:

java -Djava.security.auth.login.config=com/pingan/jaas/tutorial/sample_jaas.config -cp ".;%CLASSPATH%;C:\bea\weblogic81\server\lib\weblogic.jar;C:\bea\weblogic81\server\lib\mbeantypes\wlManagement.jar;" com.pingan.jaas.tutorial.SampleAcn

 

运行结果:

C:\bea\user_projects\applications\Test3\Test3Web\WEB-INF\classes>java -Djava.security.auth.login.config=com/pingan/jaas/tutorial/sample_jaas.config -cp ".;%CLASSPATH%;C:\bea\weblogic81\server\lib\weblogic.jar;C:\bea\weblogic81\server\lib\mbeantypes\wlManagement.jar;" com.pingan.jaas.tutorial.SampleAcn
user name: testUser
password: testPassword
                [MyLoginModule] 用户输入的用户名: testUser
                [MyLoginModule] 用户输入的密码:testPassword
                [MyLoginModule] authentication failed
user name: testUser
password: testPassword
                [SampleLoginModule] user entered user name: testUser
                [SampleLoginModule] user entered password: testPassword
                [SampleLoginModule] authentication succeeded

com.pingan.jaas.tutorial.MyLoginModule.commit(131)
---------------------------------- <2011-02-14 10:03:14> ----------------------------------
succeeded=false
---------------------------------- <2011-02-14 10:03:14> ----------------------------------


com.pingan.jaas.tutorial.SampleLoginModule.commit(131)
---------------------------------- <2011-02-14 10:03:14> ----------------------------------
succeeded=true
---------------------------------- <2011-02-14 10:03:14> ----------------------------------

                [SampleLoginModule] added SamplePrincipal to Subject
Authentication succeeded!

 

还有一个帮助类LogHelper.java:

package examples.util;

import java.text.SimpleDateFormat;
import java.util.Date;

public class LogHelper {
	private static final String 换行符 = "\r\n";
	private static final String 分隔线 = "----------------------------------";
	private static final SimpleDateFormat sf = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss");

	public static void log2Console(String msg) {
		StackTraceElement[] stackTraceElements = new Throwable()
				.getStackTrace();
		StackTraceElement stackTraceElement = stackTraceElements[1];

		StringBuffer sb = new StringBuffer();
		// sb.append(换行符);
		sb.append(换行符).append(stackTraceElement.getClassName());
		sb.append('.');
		sb.append(stackTraceElement.getMethodName()).append("(");
		sb.append(stackTraceElement.getLineNumber()).append(")");
		sb.append(换行符);
		String separateLine = buildSeparateLine();
		sb.append(separateLine);
		sb.append(msg).append(换行符);
		sb.append(separateLine);
		System.out.println(sb.toString());
	}

	public static void log2Console(String[] array) {
		StackTraceElement[] stackTraceElements = new Throwable()
				.getStackTrace();
		StackTraceElement stackTraceElement = stackTraceElements[1];

		StringBuffer sb = new StringBuffer();
		// sb.append(换行符);
		sb.append(换行符).append(stackTraceElement.getClassName());
		sb.append('.');
		sb.append(stackTraceElement.getMethodName()).append("(");
		sb.append(stackTraceElement.getLineNumber()).append(")");
		sb.append(换行符);
		String separateLine = buildSeparateLine();
		sb.append(separateLine);
		if (array == null) {
			sb.append("数组为空(NULL)").append(换行符);
		} else {
			sb.append('{');
			for (int i = 0; i < array.length; i++) {
				if (i >= 0) {
					sb.append(", ");
				}
				sb.append('"').append(array[i]).append('"');
			}
			sb.append('}').append(换行符);
		}
		sb.append(separateLine);
		System.out.println(sb.toString());
	}

	private static String buildSeparateLine() {
		StringBuffer sb = new StringBuffer();
		Date currentTime = new Date();
		sb.append(分隔线).append(" <").append(sf.format(currentTime)).append("> ")
				.append(分隔线).append(换行符);
		return sb.toString();
	}
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值