Доступ запрещен (соединение java.net.SocketPermission 127.0.0.1:8080, разрешение)

Я вставил Java-апплет на простую HTML-страницу, расположенную по адресу http://localhost:8080/index.html:

<applet id="applet" code="SomeCode.class" archive="lib.jar" Width="1" Height="1"></applet>

У Java-апплета есть метод, который похож на код ниже:

public void PostStuffToServer() {
  String server = "http://localhost:8080/PostHandler.ashx";
  URL u = new URL(server);
  URLConnection con = u.openConnection();
  con.setDoOutput(true);
  con.getOutputStream().write(stream.toByteArray());
  con.connect();
}

Когда я выполняю код апплета из JavaScript примерно так:

obj = document.getElementById('applet');
obj.getClipboardImageURL();

Я получаю следующую ошибку:

доступ запрещен (соединение java.net.SocketPermission 127.0.0.1:8080, разрешение)

Кажется, что код Java разрешает домен localhost к его эквивалентному IP-адресу и, следовательно, повышает междоменное ограничение безопасности. Он отлично работает, когда я выполняю тот же код из http://127.0.0.1:8080/index.html. Файл lib.jar подписан.

Есть ли способ избежать этого?

10 ответов

Решение

Я столкнулся с той же проблемой после установки Java 6 Update 22. Мой апплет был в сети в течение нескольких лет без сообщений об ошибках. Когда я понижаю до версии 6, обновление 21, все работает отлично. Мой апплет не подписан.

РЕШЕНИЕ: Мне понадобилось время, чтобы найти причину проблемы. На самом деле в моем случае было несколько факторов, вызывающих ошибку безопасности. Проблема была решена с помощью файла crossdomain.xml. Апплет Java попытался загрузить файл междомена, потерпел неудачу и даже не удосужился отобразить ошибку в консоли Java (уровень отладки 5). Java пыталась загрузить файл с IP-адреса моего домена (http://ip-address/crossdomain.xml), а не из корня моего сайта (http://domain-name/crossdomain.xml). Я полагаю, это лучше с точки зрения безопасности? Затем мне пришлось настроить веб-сервер так, чтобы он представлял кросс-доменный файл по IP-адресу. В моем случае я удалил веб-сайт по умолчанию в ISS по соображениям безопасности, и мне пришлось создать новый веб-сайт. Затем я обнаружил, что Java-апплет не работает с междоменными файлами, которые я использую с flash:

<?xml version="1.0"?>
<cross-domain-policy>
   <site-control permitted-cross-domain-policies="master-only"/>
   <allow-http-request-headers-from domain="*" headers="*"/>
   <allow-access-from domain="*" />
</cross-domain-policy>

Мне пришлось удалить узлы control-site и allow-http-request-headers-from из файла xml, чтобы заставить апплет работать.

Я думаю, что я опоздал, но в любом случае... Ребята, вы не можете поверить, насколько легко решение этой проблемы.

Проблема заключается в том, что код апплета Java, вызываемый из JavaScript, имеет только разрешения, которые являются пересечением кода JavaScript и кода вашего апплета - и каким-то образом разрешения JavaScript рассматриваются как меньшие, что приводит к этому Исключению.

Вот что я сделал: предположим, у вас есть функция innocentFunc() это вызывает исключение java.net.SocketPermission, поэтому ваш код выглядит примерно так:

String s = innocentFunc();

Теперь вы можете изменить его на что-то вроде этого:

String s = AccessController.doPrivileged(
      new PrivilegedAction<String>() {
          public String run() {
              return innocentFunc();
          }
        }
     );

Этот вызов AccessController в основном сообщает виртуальной машине Java, что код, который она запускает, должен подчиняться не разрешениям из цепочки вызовов, а только разрешениям самого вызывающего.

Конечно, вы должны делать что-то подобное только после того, как убедитесь, что это innocentFunc call не может сделать ничего плохого, даже если он вызван вредоносным кодом.

Я получаю то же самое с обновлением 22, а не с обновлением 21.

Я использую апплет TinyPlayer, которым я управляю через JavaScript.

Я загружаю аудиофайлы из того же домена (mydomain.example.com, IP 1.2.3.4), что и страница, на которую загружается апплет - на все ссылки ссылаются с помощью относительных URL.

Когда я пытаюсь воспроизвести звук, он не воспроизводится, и я получаю: доступ запрещен (java.net.SocketPermission 1.2.3.4:80 подключение, разрешение)

Просматривая журналы доступа, я получаю запрос на crossdomain.xml прямо перед тем, как это произойдет. Но загвоздка в том, что Java не запрашивает crossdomain.xml у mydomain.example.com/crossdomain.xml ... а вместо 1.2.3.4/crossdomain.xml

Обходное решение, которое мне подходит, - это настроить виртуальный хост, отвечающий за IP-адрес 1.2.3.4, и предоставить ему crossdomain.xml, чтобы Java могла найти crossdomain.xml в (неправильном) месте, ищу это.

Я только что проверил с содержанием:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*" />
</cross-domain-policy>

... но возможно возможно сделать это более ограничительным.

При этом звук воспроизводится правильно.

Просто добавим, что здесь есть кое-что, что точно соответствует проблеме, с которой я столкнулся, - в частности, упоминается об управлении апплетом с помощью JavaScript.

http://www.oracle.com/technetwork/java/javase/6u22releasenotes-176121.html

Исправление для CVE-2010-3560 могло привести к тому, что некоторые Java-апплеты, работающие в новом Java-плагине, перестали работать, если они встроены в веб-страницы, содержащие JavaScript, который вызывает Java для выполнения действий, требующих разрешений сетевой безопасности. Эти апплеты могут завершиться с ошибкой безопасности сети при некоторых обстоятельствах, если служба имен, которая разрешила исходное имя хоста URL веб-страницы, не возвращает совпадающее имя в результате обратного поиска адреса.

Их предложение состоит в том, чтобы добавить в DNS специальную сумасшедшую запись "просто для Java", например:

10.11.12.13    foo.bar.com.auth.13.12.11.10.in-addr.arpa

У меня была похожая проблема, и она возникает, только когда я использую "localhost" как часть URL-адреса для страницы с апплетом. Когда я использовал URL с реальным именем хоста или IP-адресом как часть URL, проблема не возникла. Я не уверен, что это дефект плагина Java...

Например, когда я использовал URL-адрес, такой как http://localhost:9080/app_id/appletPage проблема, но когда я использовал URL-адрес с использованием фактического IP-адреса или имени хоста, проблема не возникла.

IIRC, политика JavaScript одного и того же происхождения предотвращает доступ к тому же хосту / другому порту. LiveConnect подключаемого модуля применяет эту политику только для локального хоста.

Смотрите: http://download.oracle.com/javase/tutorial/deployment/applet/security.html

Неподписанные апплеты могут выполнять следующие операции:

Они могут устанавливать сетевые подключения к хосту, с которого пришли.

Если Java не преобразует исходную систему в localhost, апплет не сможет открывать сокеты.

Обновление от @Kristian выше спасло мой день.

я имел access denied (java.net.SocketPermission <server_ip>:<server port> connect,resolve) из апплета в веб-приложении.

В нашем DNS произошли изменения, в результате чего IP-адрес балансировщика нагрузки сервера приложений не преобразовывался в имя с доменом. Поэтому подозреваемое "междоменное соединение" от апплета до сервера было заблокировано. Я добавил crossdomain.xml с

<?xml version="1.0"?> <cross-domain-policy> <allow-access-from domain="*" /> </cross-domain-policy>

в <tomcat-home>/webapps и проверил, что это доступно с http://<server name>:<server port>/crossdomain.xml

Вы должны проверить ваши разрешения виртуального каталога.

Я не думаю, что возможно сделать файл crossdomain.xml более ограничительным, в настоящее время Java-апплеты поддерживают только (domain="*")

см. здесь http://www.oracle.com/technetwork/java/javase/index-135519.html

Другие вопросы по тегам