java.rmi.AccessException: Registry.rebind запрещен; origin /10.0.0.71 - нелокальный хост - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть простое приложение калькулятор клиент / сервер, использующее RMI. Сервер и клиент находятся на разных машинах Linux. IP-адрес клиента - 10.0.0.71, а IP-адрес сервера - 10.0.1.100.

Это удаленный интерфейс:

package com.simplecalc.commons;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {
    public float add(float a, float b) throws RemoteException;
}

Это код на стороне сервера, реализующий удаленный интерфейс:

package com.simplecalc.server;

import java.rmi.RemoteException;
import com.simplecalc.commons.Calculator;

public class CalculatorImpl implements Calculator {
    @Override
    public float add(float a, float b) throws RemoteException {
        float result = a + b;
        System.out.println("$ (" + a + " + " + b + ") = " + result);
        return result;
    }
}

Это код для запуска приложения на стороне сервера:

package com.simplecalc.server;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import com.simplecalc.commons.Calculator;

public class Server {

    private static void setPolicy() {
        System.setProperty("java.security.policy", "file:///calculator.policy");
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
    }

    public static void main(String[] args) throws RemoteException {
        setPolicy();
        int port = 1099;
        Calculator engine = new CalculatorImpl();
        Calculator stub = (Calculator) UnicastRemoteObject.exportObject(engine, 0);
        Registry registry = LocateRegistry.getRegistry(port);
        System.out.println("Registering calculator object ...");
        registry.rebind(Calculator.class.getSimpleName(), stub);
    }
}

Наконец, это клиент для вызова калькулятора:

package com.simplecalc.client;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import com.simplecalc.commons.Calculator;

public class CalculatorClient {

    private static void setPolicy() {
        System.setProperty("java.security.policy", "file:///calculator.policy");
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
    }

    public static void main(String[] args) throws RemoteException, NotBoundException {
        setPolicy();
        int port = 1099;
        String server="10.0.1.100";

        Registry registry = LocateRegistry.getRegistry(server, port);
        Calculator calculator = (Calculator) registry.lookup(Calculator.class.getSimpleName());
        registry.rebind(server, calculator);
        float result = calculator.add(10F, 5F);
        System.out.println("Result: " + result);
    }
}

Это файл calculator.policy:

grant {
    permission java.security.AllPermission;
    permission java.net.SocketPermission "localhost:1099", "connect, resolve";
    permission java.net.SocketPermission "127.0.0.1:1099", "connect, resolve";
    permission java.net.SocketPermission "10.0.0.71:1099", "connect, resolve";
    permission java.net.SocketPermission "localhost:80", "connect, resolve";
};

Я скомпилировал код сервера и успешно запустил rmiregistry так:

cd server_classes_directory
rmiregistry 1099 &

Тогда я успешно провел класс com.simplecalc.server.Server

Когда я запускаю класс com.simplecalc.client.CalculatorClient, я получаю исключение:

Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server     thread; nested exception is: 
    java.rmi.AccessException: Registry.rebind disallowed; origin /10.0.0.71 is non-local host
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:389)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:835)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(    StreamRemoteCall.java:283)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:260)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:375)
    at sun.rmi.registry.RegistryImpl_Stub.rebind(RegistryImpl_Stub.java:155)
    at com.simplecalc.client.CalculatorClient.main(CalculatorClient.java:27)
Caused by: java.rmi.AccessException: Registry.rebind disallowed; origin /10.0.0.71 is     non-local host
    at sun.rmi.registry.RegistryImpl.checkAccess(RegistryImpl.java:350)
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(RegistryImpl_Skel.java:128)
    at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:468)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:300)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:835)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

Есть идеи, ребята?

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Наконец я нашел проблему.

  1. Дело в том, что способ регистрации и поиска службы rmi работает только тогда, когда клиент и сервер находятся на одном компьютере.
  2. Не нужно создавать экземпляр SecurityManager
  3. Реализация удаленного интерфейса должна расширяться UnicastRemoteObject
  4. Я полностью открываю политики безопасности Java.

Это новая реализация удаленного интерфейса:

package com.simplecalc.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import com.simplecalc.commons.Calculator;

public class CalculatorImpl extends UnicastRemoteObject implements Calculator {
    @Override
    public float add(float a, float b) throws RemoteException {
        float result = a + b;
        System.out.println("$ (" + a + " + " + b + ") = " + result);
        return result;
    }
}

Это новый класс сервера:

package com.simplecalc.server;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import com.simplecalc.commons.Calculator;

public class Server {

    public static void main(String[] args) throws RemoteException {
        final int port = 1099;
        final String serverIp = "10.0.1.100";
        final String serviceName = Calculator.class.getSimpleName();
        final String url = "rmi://" + serverIp + ":" + port + "/" + serviceName;

        System.out.println("Registering calculator object ...");
        CalculatorImpl engine = new CalculatorImpl();
        Naming.rebind(url, engine);
        System.out.println("Server listening on " + url);
    }
}

Это новый клиентский класс:

package com.simplecalc.client;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import com.simplecalc.commons.Calculator;

public class CalculatorClient {

public static void main(String[] args) throws RemoteException, NotBoundException {
        final int port = 1099;
        final String serverIp = "10.0.1.100";
        final String serviceName = Calculator.class.getSimpleName();
        final String url = "rmi://" + serverIp + ":" + port + "/" + serviceName;

        Calculator calculator = (Calculator) Naming.lookup(url);
        float result = calculator.add(10F, 5F);
        System.out.println("Result: " + result);
    }
}

Файл calculator.policy:

grant {
    permission java.security.AllPermission;
};
0 голосов
/ 30 апреля 2018

Точно так же, как говорится в сообщении об ошибке, вы не можете привязывать, перепривязывать или отменять привязку к / из удаленного реестра. Вы должны быть запущены на одном хосте. Это элементарная мера безопасности RMI.

Но ваш клиент не должен делать привязку в первую очередь. Это не имеет смысла. Все, что он пытается сделать, - это привязать только что найденный сервер к тому же реестру. Просто удали его.

...