2009-09-18 136 views
3

我們在負載較重的Web服務器中使用JAAS。配置文件從一個文件中加載,任何從內存中讀取JAAS配置文件的方式

System.setProperty("java.security.auth.login.config", "/config/jaas.config"); 

在分析中,我們注意到,配置從文件加載每次登錄嘗試。這是我們試圖避免的I/O操作。無論如何將JAAS配置存儲在內存中?

回答

4

你可以實現你自己的Configuration。 Javadoc中說:

默認配置 實現可以通過 設置 「login.configuration.provider」 安全屬性的值被改變(在Java 安全屬性文件中)完全 合格所需的名稱 配置實施類。

默認實現com.sun.security.auth.login.ConfigFile (source)似乎在每次實例化類時加載文件。您可以緩存內容。對安全性方面沒有任何評論。

4

下面的代碼片段與一個內存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; 
      } 
     }; 

    } 

} 
+1

偉大的回答,對我幫助很大!雖然不推薦使用私有類「Krb5LoginModule」,但需要在項目的庫中包含「rt.jar」。 – lazlev 2017-03-29 15:24:27

+0

@lazlev,謝謝。我更新了代碼。 – 2017-04-08 17:47:58