如何在不使用私有 API 的情况下使用 java.net.Authenticator 防止两个不同用户之间泄露凭据?

Tre*_*kaz 5 java authentication

Java 9 将最终阻止我们使用 sun 内部类。

我们仍然拥有的一种这样的用法如下:

import sun.net.www.protocol.http.AuthCache;
import sun.net.www.protocol.http.AuthCacheValue;

public static void authenticationHacks() {
    AuthCacheValue.setAuthCache(new NullAuthCache());
}

//...

class NullAuthCache implements AuthCache {
    @Override
    public void put(String s, AuthCacheValue authCacheValue) {
    }

    @Override
    public AuthCacheValue get(String s, String s1) {
        return null;
    }

    @Override
    public void remove(String s, AuthCacheValue authCacheValue) {
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有公​​共替代品?

就 XY 问题的 X 而言,这是在单个应用程序中运行的多个用户的解决方法,该应用程序使用java.net.URL. 如果您不执行此 hack,第一个成功通过身份验证的用户的凭据将被保留并传递给其他服务器以用于实际属于不同用户的请求。

如果有其他方法可以做到这一点,我想知道。我认为这是 JRE 中的一个错误,所以如果他们从那时起修复了它,那也很高兴知道。

作为手头问题的一个示例,仅使用公开可用的 API,您会遇到以下问题:

public class AuthenticationLeakBugDemo {
    public static void main(String[] args) throws Exception {
        // User 1
        {
            System.out.println("Simulating user 1 coming in " +
                "without authentication at first.");
            System.out.println("Expecting: 401");
            URL url = new URL("http://httpbin.org/basic-auth/a/a");
            HttpURLConnection connection = (HttpURLConnection)
                url.openConnection();
            System.out.println("Got: " + connection.getResponseCode());
        }

        // User 1
        {
            System.out.println("Simulating user 1 coming in " +
                "with proper authentication.");
            System.out.println("Expecting: 200");
            Authenticator.setDefault(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("a", "a".toCharArray());
                }
            });
            try {
                URL url = new URL("http://httpbin.org/basic-auth/a/a");
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                System.out.println("Got: " + connection.getResponseCode());
            } finally {
                Authenticator.setDefault(null);
            }
        }

        // User 2
        {
            System.out.println("Simulating user 2 coming in with no authentication.");
            System.out.println("Expecting: 401");
            URL url = new URL("http://httpbin.org/basic-auth/a/a");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            System.out.println("Got: " + connection.getResponseCode());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出当然是:

import sun.net.www.protocol.http.AuthCache;
import sun.net.www.protocol.http.AuthCacheValue;

public static void authenticationHacks() {
    AuthCacheValue.setAuthCache(new NullAuthCache());
}

//...

class NullAuthCache implements AuthCache {
    @Override
    public void put(String s, AuthCacheValue authCacheValue) {
    }

    @Override
    public AuthCacheValue get(String s, String s1) {
        return null;
    }

    @Override
    public void remove(String s, AuthCacheValue authCacheValue) {
    }
}
Run Code Online (Sandbox Code Playgroud)

表明 Java 的内部身份验证缓存已将一个用户的凭据泄露给另一个用户。:(