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

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

На данный момент я проигнорировал dll EFTPOS и создал простую DLL-библиотеку, украшенную JNI, на моем языке выбора (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 жестко запрограммирована, чтобы не разрешать такие разрешения для апплета из-за угрозы безопасности.

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

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

Майк

3 ответа

Решение

Вы определенно можете сделать это. У меня есть рабочий апплет в производстве, который делает именно это. Даже если ваш апплет подписан, вам все равно нужно использовать 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 по пути в windows, чтобы апплет мог ее найти.

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

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

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

Удачи.

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