我們在負載較重的Web服務器中使用JAAS。配置文件從一個文件中加載,任何從內存中讀取JAAS配置文件的方式
System.setProperty("java.security.auth.login.config", "/config/jaas.config");
在分析中,我們注意到,配置從文件加載每次登錄嘗試。這是我們試圖避免的I/O操作。無論如何將JAAS配置存儲在內存中?
我們在負載較重的Web服務器中使用JAAS。配置文件從一個文件中加載,任何從內存中讀取JAAS配置文件的方式
System.setProperty("java.security.auth.login.config", "/config/jaas.config");
在分析中,我們注意到,配置從文件加載每次登錄嘗試。這是我們試圖避免的I/O操作。無論如何將JAAS配置存儲在內存中?
你可以實現你自己的Configuration。 Javadoc中說:
默認配置 實現可以通過 設置 「login.configuration.provider」 安全屬性的值被改變(在Java 安全屬性文件中)完全 合格所需的名稱 配置實施類。
默認實現com.sun.security.auth.login.ConfigFile (source)似乎在每次實例化類時加載文件。您可以緩存內容。對安全性方面沒有任何評論。
下面的代碼片段與一個內存JAAS配置連接到PostgreSQL數據庫(使用pgjdbc和HikariCP),即沒有Configuration
文件是必需的:
package com.vlkan.kerberos.auth;
import com.google.common.collect.ImmutableMap;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import static com.google.common.base.Preconditions.checkArgument;
public enum Main {;
private static final String JAAS_CONFIG_NAME = "pgjdbc";
public static void main(String[] args) throws LoginException, SQLException {
String jdbcUrl = "jdbc:postgresql://host/dbname";
String jdbcDriver = "org.postgresql.Driver";
String username = "user";
String password = "pass";
Configuration jaasConfig = createJaasConfig();
Configuration.setConfiguration(jaasConfig);
HikariConfig hikariConfig = createHikariConfig(jdbcUrl, jdbcDriver, username, password);
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
try (Connection connection = dataSource.getConnection()) {
try (PreparedStatement statement = connection.prepareStatement("SELECT 1")) {
try (ResultSet resultSet = statement.executeQuery()) {
boolean next = resultSet.next();
checkArgument(next, "no results");
int result = resultSet.getInt(1);
checkArgument(result == 1, "expecting: 1, found: %s", result);
System.out.println("ok");
}
}
}
}
private static HikariConfig createHikariConfig(String jdbcUrl, String jdbcDriver, String username, String password) {
HikariConfig config = new HikariConfig();
config.setDriverClassName(jdbcDriver);
config.setJdbcUrl(jdbcUrl);
config.setUsername(username);
config.setPassword(password);
fixKerberosProperties(config, username, password);
return config;
}
private static void fixKerberosProperties(HikariConfig config, String username, String password) {
Properties properties = new Properties();
properties.setProperty("user", username);
properties.setProperty("password", password);
properties.setProperty("JAASConfigName", JAAS_CONFIG_NAME);
config.setDataSourceProperties(properties);
}
private static Configuration createJaasConfig() {
// Create entry options.
Map<String, Object> options = ImmutableMap.of(
"useFirstPass", "false", // Do *not* use javax.security.auth.login.{name,password} from shared state.
"debug", "true" // Output debug (including plain text username and password!) messages.
);
// Create entries.
AppConfigurationEntry[] entries = {
new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
options)
};
// Create configuration.
return new Configuration() {
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
checkArgument(JAAS_CONFIG_NAME.equals(name));
return entries;
}
};
}
}
偉大的回答,對我幫助很大!雖然不推薦使用私有類「Krb5LoginModule」,但需要在項目的庫中包含「rt.jar」。 – lazlev 2017-03-29 15:24:27
@lazlev,謝謝。我更新了代碼。 – 2017-04-08 17:47:58