Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

Tomcatのレルムを独自に実装して認証する

どこかの海外blogから。

パスワードを暗号化してデータベースに登録するとき、暗号化ライブラリを利用するとTomcatの認証がそのままでは使えないので、レルムを実装する。

たとえばJasyptを使って暗号化しているとき、TomcatのRealmBaseの継承階層を利用して独自のレルムを作成し、Jasyptでのパスワードチェックをする。

import java.security.Principal;
import java.sql.Connection;
import java.util.ArrayList;

import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.realm.JDBCRealm;
import org.jasypt.util.password.StrongPasswordEncryptor;

public class JdbcJasyptRealm extends JDBCRealm {

	@Override
	public synchronized Principal authenticate(Connection dbConnection, String username, String credentials) {

		if (username == null) {
			return null;
		}

		String dbCredentials = getPassword(username);

		StrongPasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
		boolean isValid = passwordEncryptor.checkPassword(credentials, dbCredentials);

		if (isValid) {
			if (containerLog.isTraceEnabled())
				containerLog.trace(sm.getString("jdbcRealm.authenticateSuccess", username));
		} else {
			if (containerLog.isTraceEnabled())
				containerLog.trace(sm.getString("jdbcRealm.authenticateFailure", username));
			return null;
		}

		ArrayList<String> roles = getRoles(username);

		return new GenericPrincipal(this, username, credentials, roles);
	}
}

そのレルムを利用するようにTomcatのcontext.xmlに追記する。

<Context>
...
	<Realm className="xxx.xxx.JdbcJasyptRealm"
		driverName="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/xxxxxx"
		connectionName="xxxxxxxxx" connectionPassword="xxxxxxxxx"
		userTable="user" userNameCol="user_name" userCredCol="user_password"
		userRoleTable="role" roleNameCol="user_role" />
...
</Context>

実装したレルムクラスをJARファイルにしてCATALINA_HOME\libディレクトリに配置する。

Jasyptを使うならそのJARもlibディレクトリに配置する必要がある。