Вызов DLL из апплета через JNI

У меня есть "доказательство концепции" работы, которая пересекается на какую-то незнакомую территорию. Мне поручено подключить машину EFTPOS к приложению, запущенному как апплет в браузере в нашей интрасети.

Я проигнорировал dll EFTPOS на данный момент и создал простую JNI-украшенную DLL на моем выбранном языке (Delphi), который просто записывает строку в текстовый файл в c: \, и я могу успешно ее вызвать из локального Java-приложения.

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

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

Есть запись, которую вы можете поместить в файл java.policy, чтобы разрешить loadLibrary. а также allPermission, и я пробовал целый ряд вариантов по этим строкам, но безрезультатно, создавая следующую трассировку ошибок в консоли Java:

java.lang.ExceptionInInitializerError
  at app.TestApplet.LogAString(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.lang.reflect.Method.invoke(Unknown Source)
  at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
  at sun.plugin.com.MethodDispatcher.invoke(Unknown Source)
  at sun.plugin.com.DispatchImpl.invokeImpl(Unknown Source)
  at sun.plugin.com.DispatchImpl$1.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.plugin.com.DispatchImpl.invoke(Unknown Source)
Caused by: java.security.AccessControlException: access denied (java.lang.RuntimePermission loadLibrary.DLoggerImpl)
  at java.security.AccessControlContext.checkPermission(Unknown Source)
  at java.security.AccessController.checkPermission(Unknown Source)
  at java.lang.SecurityManager.checkPermission(Unknown Source)
  at java.lang.SecurityManager.checkLink(Unknown Source)
  at java.lang.Runtime.loadLibrary0(Unknown Source)
  at java.lang.System.loadLibrary(Unknown Source)
  at app.DLogger.<clinit>(Unknown Source)
  ... 16 more
java.lang.Exception: java.lang.ExceptionInInitializerError
  at sun.plugin.com.DispatchImpl.invokeImpl(Unknown Source)
  at sun.plugin.com.DispatchImpl$1.run(Unknown Source)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

Ключевая строка, похоже, "вызвана: java.security.AccessControlException: доступ запрещен (java.lang.RuntimePermission loadLibrary.DLoggerImpl)", что подразумевает проблему с разрешениями. Возможно, я ошибаюсь в неправильном файле политики или неправильном подписи, или что-то вроде этого, или может быть, что Java жестко не разрешает подобные разрешения для апплета из-за угрозы безопасности.

Мой вопрос: я трачу свое время? Можно ли это сделать, и если да, то как?

Спасибо в ожидании

Mike

Ответ 1

Вы можете это сделать. У меня есть рабочий апплет в производстве, который делает именно это. Даже если ваш апплет подписан, вам все равно нужно использовать Access Controller для доступа к DLL, вы не можете просто вызвать "loadlibrary". Вы можете добавить это в файл политики Java, однако это не рекомендуется из-за 1. Вероятно, у вас нет доступа к конфигурации java для пользователей. 2. Даже если это используется для вашей собственной компании, управление файлом политики - это боль, поскольку пользователи загружают некоторую JRE, а файл политики либо перезаписывается, либо игнорируется.

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

try
{
    AccessController.doPrivileged(new PrivilegedAction()
    {
        public Object run()
        {
            try
            {
                // privileged code goes here, for example:
                System.load("C:/Program Files/.../Mydll.dll");
                return null; // nothing to return
            }
            catch (Exception e)
            {
                System.out.println("Unable to load Mydll");
                return null;
            }
        }
     });
}
catch (Exception e)
{
    System.out.println("Unable to load Mydll");
}

Вы также можете использовать System.loadlibrary(mydll.dll), но вы должны иметь папку dll на пути в окнах, чтобы апплет мог ее найти.

Если вам нужны некоторые исходные образцы для вызова функций JNI, дайте мне знать, что я тоже могу это сделать.

Ответ 2

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

Ответ 3

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

Удачи.