2008-10-07 2 views
15

Вчера я попытался начать работу с Java RMI. Я нашел этот учебник по солнцу (http://java.sun.com/docs/books/tutorial/rmi/index.html) и начал с реализации сервера. Но каждый раз, когда я запускаю пограмму (rmiregistry работает) я получаю AccessControlException со следующим StackTrace:Java RMI Tutorial - AccessControlException: доступ запрещен (java.io.FilePermission

LoginImpl exception: 
java.security.AccessControlException: access denied (java.io.FilePermission \\\C\ProjX\server\serverProj\bin\usermanager read) 
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:264) 
    at java.security.AccessController.checkPermission(AccessController.java:427) 
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) 
    at java.lang.SecurityManager.checkRead(SecurityManager.java:871) 
    at java.io.File.exists(File.java:700) 
    at sun.net.www.protocol.file.Handler.openConnection(Handler.java:80) 
    at sun.net.www.protocol.file.Handler.openConnection(Handler.java:55) 
    at java.net.URL.openConnection(URL.java:943) 
    at sun.rmi.server.LoaderHandler.addPermissionsForURLs(LoaderHandler.java:1020) 
    at sun.rmi.server.LoaderHandler.access$300(LoaderHandler.java:52) 
    at sun.rmi.server.LoaderHandler$Loader.<init>(LoaderHandler.java:1108) 
    at sun.rmi.server.LoaderHandler$Loader.<init>(LoaderHandler.java:1089) 
    at sun.rmi.server.LoaderHandler$1.run(LoaderHandler.java:861) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.server.LoaderHandler.lookupLoader(LoaderHandler.java:858) 
    at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:541) 
    at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628) 
    at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294) 
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238) 
    at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1494) 
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1457) 
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1693) 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339) 
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source) 
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375) 
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240) 
    at sun.rmi.transport.Transport$1.run(Transport.java:153) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.transport.Transport.serviceCall(Transport.java:149) 
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701) 
    at java.lang.Thread.run(Thread.java:595) 
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source) 
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source) 
    at sun.rmi.server.UnicastRef.invoke(Unknown Source) 
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source) 
    at startserver.StartServer.main(StartServer.java:22) 

Мой файл server.policy выглядит следующим образом:

grant { 
    permission java.security.AllPermission; 
}; 

Но I've также попробовал этот ...

grant { 
    permission java.security.AllPermission; 
    permission java.io.FilePermission "file://C:/ProjX/server/serverProj/bin/usermanager", "read"; 
}; 

... и это один (и несколько других :-():

grant codeBase "file:///-" { 
    permission java.security.AllPermission; 
}; 

Но в любом случае, результат будет тот же. И да, файл политики находится в пути (я вижу Parse Exception, когда я пишу неправильные записи в файл политики). Я опробовал несколько других «/» и «\» созвездий, но это не имеет никакого эффекта.

Я использую Eclipse, и мои VM-параметры, как это:

-cp C:\ProjX\server\serverProj\bin\usermanager\ 
-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/ 
-Djava.rmi.server.hostname=XYZ (anonymized) 
-Djava.security.policy=server.policy 

Составленный Дистанционно интерфейс и интерфейс класса-реализации (LoginImpl) классов в этом пути: «C:/ProjX/сервер/serverProj/бен/usermanager /». Основной метод, где я и перепривязываю создание экземпляра заглушки в реестр находится в другом пакете, и выглядит следующим образом:

public static void main(String[] args) { 
    if (System.getSecurityManager() == null) { 
     System.setSecurityManager(new SecurityManager()); 
    } 
    try { 
     String name = "Login"; 
     Login login = new LoginImpl(); 
     Login stub = (Login) UnicastRemoteObject.exportObject(login, 0); 
     Registry registry = LocateRegistry.getRegistry(); 
     registry.rebind(name, stub); 
     System.out.println("LoginImpl bound"); 
    } catch (Exception e) { 
     System.err.println("LoginImpl exception:"); 
     e.printStackTrace(); 
    } 
} 

ли кто-нибудь есть совет для меня? Спасибо за помощь.


Таким образом, вопрос и то же (java.rmi.UnmarshalException показывает, что изменение кодовую не является решением моего AccessControlException). И нет: я не хочу покупать плагин «G B» ;-).

+0

У меня была аналогичная проблема. Я разрешил это с помощью этого подхода - https://stackoverflow.com/a/44275905/1509058 – 2017-05-31 05:02:21

ответ

7

Предоставление всех разрешений на весь код очень плохо. Любой клиент RMI мог делать то, что он хотел, как зарегистрированный пользователь. В общем, попробуйте ограничить разрешения настолько же разумными, особенно когда вы не знаете, откуда пришел код.

Вернуться к вопросу ...

-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/ 

Это должно быть либо "file:///C:/..." или "file:/C:/...". Подумайте о http. "http://C:/..." относится к узлу с именем C. Обратите внимание, что сообщение об исключении удалило двоеточие, потому что это просто синтаксис для номера порта.

Причина, по которой вы получаете исключение безопасности, даже если вы предоставляете разрешения для всего кода, заключается в том, что RMI ограничивает права доступа к соответствующим URL-адресам (используя AccessController doPrivileged two argument form).

+0

Эй! Я нашел, что это очень полезно. Не могли бы вы рассказать мне, где хранить текстовый файл server.policy? – user1799214 2016-02-14 05:48:16

+0

@ user1799214 Исходный плакат использовал текущий рабочий каталог hte-сервера, указав с помощью `-Djava.security.policy = server.policy`. (Как всегда, удаление ограничений для кода, доступного в сети, сложно сделать безопасно.) – 2016-02-14 19:54:48

0

Я думаю, что исключение на самом деле выходит из rmiregistry. Эта часть трассировки стека заставляет меня так думать. Штук для rmiregistry получает исключение и передает его обратно в результате попытки переподтвердить.

 
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source) 
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source) 
    at sun.rmi.server.UnicastRef.invoke(Unknown Source) 
    at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source) 

Попробуйте запустить rmiregistry с -J-Djava.security.policy=all.policy, где файл политики предоставляет все права доступа (по крайней мере, чтобы получить вещи, идущие).

В конце концов вы также можете перейти на URL-адрес базы данных HTTP, чтобы вы могли запускать клиенты на машине отдельно от вашего сервера.

7

Хорошо, у меня оно есть. Это wasn ´ t свойство rmiregistry (работает без каких-либо параметров). Существовало две ошибки в моем кодовой базе VM-параметре:

-cp C:\ProjX\server\serverProj\bin\usermanager\ 
-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/ 
-Djava.rmi.server.hostname=XYZ (anonymized) 
-Djava.security.policy=server.policy 

... вместо этого следует выглядеть следующим образом:

-Djava.rmi.server.codebase=file:/C:/ProjX/server/serverProj/bin/ 
-Djava.rmi.server.hostname=XYZ (anonymized) 
-Djava.security.policy=server.policy 

=> Файл:/(только один слэш) + неправильный пакет концовка.

Но след был настолько запутанным, моя первая мысль заключалась в том, что что-то должно быть неправильно с политическим файлом или политикой.

Тем не менее: Благодарим вас за помощь и счастливое взломание. ;-)

2

Вы также можете установить программно java.rmi.server.codebase свойства:

Hello h = null; 
Properties props = System.getProperties(); 
System.setProperty("java.rmi.server.codebase", "file:/C:/PROJECTX/bin/"); 
try { 
    h = new HelloImpl(); 
    Naming.bind("//localhost:1099/HelloService", h); 
    System.out.println("Serwis gotów..."); 
} catch (RemoteException e) { 
    e.printStackTrace(); 
} catch (MalformedURLException e) { 
    e.printStackTrace(); 
} catch (AlreadyBoundException e) { 
    e.printStackTrace(); 
} 

для некоторой гипотетической Hello службы RMI.

0

У меня есть очень короткий вопрос ...

Почему он использует этот путь: "Файл: // C:/ProjX/сервер/serverProj/bin/usermanager" я предполагаю, что он находится в окнах, и путь в окнах записываются C: \ ProjX ...... Я спрашиваю, потому что у меня есть некоторые проблемы с RMI тоже, но у меня есть файл политика в этой моде:

grant codebase  
"file:///C:\Users\anna\Desktop\lab5\Eclipse\ProgramareServer\programare.jar-" { 
    permission java.security.AllPermission; 
}; 

является ли это так?

0

Он просто отлично работает, когда я исправил переменную CLASSPATH перед запуском реестра rmi. Я думаю, идея состоит в том, что реестр RMI загрузит ваши удаленные заглушки, и у него должен быть доступ. Это было легко, поместив мои классы в CLASSPATH перед запуском реестра. Таким образом, это не связано с какой-либо другой причиной, такой как JDK 7 или файл:/protocol.

Смежные вопросы