2008-10-07 4 views
15

어제 Java RMI를 사용해 보았습니다.이 태양 튜토리얼 (http://java.sun.com/docs/books/tutorial/rmi/index.html)을 발견하고 서버 구현을 시작했습니다. rmiregistry에 나는 다음과 같은 스택 트레이스를 나타내는 AccessControlException를 얻을) 실행 :Java RMI 튜토리얼 - 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 파일은 다음과 같습니다 I've는이 일을 시도

grant { 
    permission java.security.AllPermission; 
}; 

그러나

...

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

...이 하나의 (그리고 몇몇 다른 :-() :

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

그러나 모든 경우에 결과가 동일

. 예, 정책 파일이 경로에 있습니다 (정책 파일에 잘못된 문장을 쓸 때 구문 분석 예외가 나타납니다). 다른 여러 "/"및 "\"별자리를 사용해 보았지만 효과가 없습니다. 이클립스 내 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/bin/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 –

답변

7

모든 코드에 대한 모든 권한 부여는 정말 나쁩니다. 모든 RMI 클라이언트는 로그인 한 사용자로서 원하는대로 할 수 있습니다. 일반적으로 코드가 어디서 왔는지 알지 못하는 경우 일반적으로 합리적인 수준으로 사용 권한을 제한하십시오. 위로 질문에

... "file:///C:/..." 또는 "file:/C:/..."이어야한다
-Djava.rmi.server.codebase=file://C:/ProjX/server/serverProj/bin/usermanager/ 

. http를 생각해보십시오. "http://C:/..."C이라는 호스트를 나타냅니다. 포트 번호의 구문 일 뿐이므로 예외 메시지가 콜론을 삭제했습니다.

모든 코드에 권한을 부여하더라도 보안 예외가 발생하는 이유는 RMI가 관련 URL (AccessController doPrivileged 두 개의 인수 양식 사용)에서 적절한 권한으로 제한한다는 것입니다.

+0

안녕하세요! 나는 이것이 매우 도움이되는 것을 알았다. server.policy 텍스트 파일을 어디에 저장할 지 알려주시겠습니까? – user1799214

+0

@ user1799214 원래 포스터는'-Djava.security.policy = server.policy'를 사용하여 hte 서버의 현재 작업 디렉토리를 사용했습니다. (항상 그렇듯이, 네트워크 액세스 가능 코드의 제한을 제거하는 것은 안전하지 못합니다.) –

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) 

정책 파일의 모든 권한을 부여 -J-Djava.security.policy=all.policy와 rmiregistry의를 실행 해보십시오 (적어도 일을 가야합니다).

마지막으로 HTTP 코드베이스 URL로 전환하여 서버와 다른 컴퓨터에서 클라이언트를 실행할 수도 있습니다.

7

네, 알겠습니다. ´ rmiregistry 등록 정보가 없습니다 (매개 변수없이 작동).

-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 

=> 파일 :/(하나의 슬래시) + 잘못된 패키지 결말 내 코드베이스 VM-매개 변수에 두 개의 오류가 발생했습니다.

그러나 추적은 혼란 스러웠습니다. 첫 번째 생각은 정책 파일이나 정책 구성에 문제가 있다는 것입니다.

그럼에도 불구하고 도움과 해피 해킹에 감사드립니다. 일부 가상 Hello RMI 서비스에 대한

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(); 
} 

: ;-)

2

은 또한 프로그램 상 java.rmi.server.codebase에 속성을 설정할 수 있습니다.

+0

이 속성을 설정할 수없는 것 같습니다. 내 자바 설정 작업을 실행하는 것을 허용하지 것 같다. –

0
나는 매우 짧은 질문이

...

그는이 경로를 사용하는 이유는 무엇

: "파일 : // C :/ProjX/서버/serverProj/빈/usermanager"나는 그가 창에서 추측 , 내가 너무 RMI 몇 가지 문제가 있기 때문에 내가 물어하지만이 방식으로 정책 파일이 \ ProjX ...... :

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

잘못입니다 및 Windows에서 경로는 C를 작성 하였는가?

0

rmi 레지스트리를 시작하기 전에 CLASSPATH 변수를 수정하면 올바르게 작동합니다. RMI 레지스트리가 원격 스텁을로드하고 액세스해야한다는 아이디어가 있다고 생각합니다. 레지스트리를 실행하기 전에 클래스를 CLASSPATH에두면 간단합니다. 따라서 JDK 7이나 file :/protocol과 같은 다른 이유와 관련이 없습니다.