Сбросить учетные данные аутентификатора - PullRequest
7 голосов
/ 26 января 2009

У нас есть статический метод в служебном классе, который загружает файл с URL-адреса. Аутентификатор был настроен так, что, если требуются имя пользователя и пароль, можно получить учетные данные. Проблема заключается в том, что учетные данные из первого успешного соединения используются для каждого послесловия соединения, если учетные данные действительны. Это проблема, потому что наш код является многопользовательским, и поскольку учетные данные не проверяются для каждого соединения, возможно, что пользователь без надлежащих учетных данных мог загрузить файл.

Вот код, который мы используем

private static URLAuthenticator auth;

public static File download(String url, String username, String password, File newFile)
{
    auth.set(username, password);
    Authenticator.setDefault(auth);
    URL fURL = new URL(url);
    OutputStream out = new BufferedOutputStream(new FileOutputStream(newFile));
    URLConnection conn = fURL.openConnection();
    InputStream in = conn.getInputStream();

    try
    {
        copyStream(in, out);
    }
    finally
    {
        if (in != null)
            in.close();
        if (out != null)
            out.close();
    }

    return newFile;
}

public class URLAuthenticator extends Authenticator
{
    private String username;
    private String password;

    public URLAuthenticator(String username, String password)
    {
         set(username, password);
    }

    public void set(String username, String password)
    {
        this.username = username;
        this.password = password;
    }

    protected PasswordAuthentication getPasswordAuthentication()
    {
        log.debug("Retrieving credentials '" + username + "', '" + password + "'.");
        return new PasswordAuthentication(username, password.toCharArray());
    }
}

Я вижу инструкцию log из getPasswordAuthentication один раз, при первой загрузке файла. После этой первой успешной попытки getPasswordAuthentication больше не вызывается, даже если учетные данные были сброшены. В результате после первого успешного подключения могут быть введены недействительные учетные данные и все еще может быть установлено успешное подключение. Возможно, это результат того, что метод загрузки является статическим и находится в статическом классе?

Редактировать Я забыл упомянуть, что это в веб-приложении JSF, работающем под tomcat - может быть, одна из тех технологий устанавливает где-то некоторые учетные данные по умолчанию?

Я вытащил URLAuthenticator в его собственный класс и сделал его как можно более нестатичным, но проблема все еще существует. Я читал, что если для аутентификатора по умолчанию установлено значение null с Authenticator.setDefault (null), то в Windows будет использоваться аутентификация NTLM. Это не должно быть проблемой здесь, так как я устанавливаю Аутентификатор каждый раз, но я думал, что выкину его там. Аутентификация NTLM определенно используется, потому что, если сервер запускается как пользователь, имеющий доступ к загруженному файлу, учетные данные даже не запрашиваются, файл просто загружается. Так что что-то, очевидно, захватывает мои учетные данные и передает их до вызова аутентификатора.

Ответы [ 4 ]

10 голосов
/ 28 января 2009

Я кое-что понял по крайней мере. Похоже, что это поведение ошибка . Обходной путь - использовать специальный класс Sun для явного сброса кэша, например:

import sun.net.www.protocol.http.AuthCacheValue;
import sun.net.www.protocol.http.AuthCacheImpl;
....
AuthCacheValue.setAuthCache(new AuthCacheImpl());
Authenticator.setDefault(new URLAuthenticator(username, password));

Я сбрасываю AuthCache вверху функции загрузки, описанной в вопросе. Во время компиляции вы получите предупреждения об использовании этих классов. Это не решает проблему полностью: если аутентификация NTLM работает, аутентификатор все равно не будет вызван, но пока сервер работает под пользователем, у которого нет разрешения для запрошенного файла, это должно очистить кеш вне.

5 голосов
/ 09 апреля 2013

Столкнувшись с той же проблемой, ни один из этих ответов не помог мне. Мне потребовалось некоторое время и просмотр источника времени выполнения Java, чтобы понять это. Sun.net.www.protocol.http.ntlm.NTLMAuthentication пытается использовать прозрачную аутентификацию, что в основном использует учетные данные текущего пользователя для входа на удаленный сервер. В моем сценарии сервер-сервер (сервер Java EE для Sharepoint) это было неприемлемо. Чтобы отключить прозрачную аутентификацию, мы должны сообщить провайдеру аутентификации, что соединение не является доверенным, и оно должно проходить аутентификацию при каждом вызове:

static {
    NTLMAuthenticationCallback.setNTLMAuthenticationCallback(new NTLMAuthenticationCallback()
    {
        @Override
        public boolean isTrustedSite(URL url)
        {
            return false;
        }
    });
}        
2 голосов
/ 26 января 2009

Похоже, что в вашем блоке finally вам нужно позвонить

Authenticator.setDefault(null);
1 голос
/ 18 мая 2011

Вот рабочий код (т.е. getPasswordAuthentication (), вызываемый для каждого запроса). Вы увидите предупреждение компиляции, которое можно игнорировать.

static class MyCache implements sun.net.www.protocol.http.AuthCache{
     public void put(String pkey, sun.net.www.protocol.http.AuthCacheValue value){

     }
     public sun.net.www.protocol.http.AuthCacheValue get(String pkey, String skey){
         return null;
     }
     public void remove(String pkey, sun.net.www.protocol.http.AuthCacheValue entry){

     }
}
static{
    sun.net.www.protocol.http.AuthCacheValue.setAuthCache(new MyCache());

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...