How to solve java.security.AccessControlException - java

I need suggestions concerning the java.security.AccessControlException, I get when executing the following code. (I have consulted similar questions here but didn't success to make it work)
Here is my server code:
public class GetPageInfos extends UnicastRemoteObject implements RemoteGetInfo{
private static final String url="http://www.lemonde.fr/";
public class GetPageInfos extends UnicastRemoteObject implements RemoteGetInfo{
private static final String url="http://www.lemonde.fr/";
public GetPageInfos() throws RemoteException{
}
public String getSiteInfos() throws RemoteException {
Document doc;
try {
doc = Jsoup.connect(url).get();
String title = doc.title();
return "title is "+title;
} catch (IOException e) {
System.out.println("Faild! "+e.getMessage());
return "not found";
}
}
public static void main(String[] args){
try {
GetPageInfos infos= new GetPageInfos();
//System.setProperty("java.rmi.server.hostname","5lq04x1.gemalto.com");
Naming.rebind("RemoteGetInfo", infos);
/*GetPageInfos obj=new GetPageInfos();
RemoteGetInfo stub = (RemoteGetInfo) UnicastRemoteObject.exportObject(obj, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("RemoteGetInfo", stub);
*/
System.out.println("server ready");
} catch (RemoteException e) {
System.out.println("GetPageInfos "+e.getMessage());
}
catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here is my client code:
//RMI Client
public class PrintSiteInfos {
public static void main(String arg[])
{
System.setSecurityManager(new RMISecurityManager());
try
{
/*String host=null;
Registry registry = LocateRegistry.getRegistry(host);
RemoteGetInfo stub = (RemoteGetInfo) registry.lookup("RemoteGetInfo");
String response = stub.getSiteInfos();
System.out.println(response); */
RemoteGetInfo obj = (RemoteGetInfo) Naming.lookup( "RemoteGetInfo");
System.out.println(obj.getSiteInfos());
}
catch (Exception e)
{
System.out.println("PrintSiteInfos exception: " + e.getMessage());
e.printStackTrace();
}
}
}
So I got
exception: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve")
I found that I have to pass a policy file which I have like:
grant {
permission java.security.AllPermission;};
But how? Anyother suggestions?

You may grant only the socket permission not all permissions (which might be a security risk). Thus something like:
grant {
permission java.net.SocketPermission "127.0.0.1:1099", "connect, resolve";
};
Two ways to do it:
1) As an argument at the command line
java -Djava.security.policy=mypolicyfile PrintSiteInfo
2) within the JRE environment:
Add the permission in the JRE_HOME/lib/security/java.policy file

Get rid of the security manager. You don't need it unless you're using the RMI codebase feature.

Related

Change JVM Properties Using WebSphere MBeans

I'm trying to create a java program that will edit the class path properties of the JVM on WebSphere. I am now able to connect the program to the server and also find the node, but I don't know what to do next. Which MBean should I use to be able to find the JVM Classpath and configure it? I know I can edit it on the AdminConsole itself, but for this task, I would really have to do it using a Java Program.
I am also not allowed to use wsadmin and jacl/jython scripts.
Here is my code so far:
public class Expi
{
private AdminClient adminClient;
private ObjectName nodeAgent;
private AdminService adminSF;
String hostName = "localhost";
String hostPort = "8880";
String nodeName = "node1";
String servName = "server1";
public static void main(String [] args) throws NamingException, AdminException
{
Expi xp = new Expi();
xp.createAdminClient();
xp.getNodeAgentMBean(nodeName);
xp.testMB();
}
private void createAdminClient()
{
// Set properties for the connection
Properties connectProps = new Properties();
connectProps.setProperty(
AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
connectProps.setProperty(AdminClient.CONNECTOR_HOST, hostName);
connectProps.setProperty(AdminClient.CONNECTOR_PORT, hostPort);
connectProps.setProperty(AdminClient.USERNAME, hostName);
connectProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "false");
// Connection Status Update
try
{
adminClient = AdminClientFactory.createAdminClient(connectProps);
System.out.println("Connected to SOAP Connection!");
}
catch (java.lang.Exception e)
{
System.out.println("Exception creating admin client: " + e);
System.exit(-1);
}
}
private void getNodeAgentMBean(String nodeName) throws NamingException
{
// Finding the specified node
try
{
String query = "WebSphere:type=Server,node="+ nodeName + ",*";
ObjectName queryName = new ObjectName(query);
Set s = adminClient.queryNames(queryName, null);
if (!s.isEmpty())
{
nodeAgent = (ObjectName)s.iterator().next();
System.out.println("Specified Node Found:" + nodeName);
}
else
{
System.out.println("Node agent MBean was not found");
System.exit(-1);
}
}
catch (MalformedObjectNameException e)
{
System.out.println(e);
System.exit(-1);
}
catch (java.lang.Exception e)
{
System.out.println(e);
System.exit(-1);
}
}
private void testMB() //find the correct MBean and use it to edit the values
{
AdminServiceFactory.getAdminService();
AdminServiceFactory.getMBeanFactory();
}
}
Any help would really be appreciated. Thank you!
You can execute the admin command using the AdminClient API. It is very difficult for to find out specific action since it is not well documented like JACL or JYTHON.
Sample available below for simple "listNodes" command. You can use the same approach to "listServers" and get the specific server object you want to modify. Once the server object is obtained, you can look at the same documentation below for executing command on specific target object.
AdminCommand cmd = cmdMgr.createCommand("listNodes");
cmd.setConfigSession(session);
AsyncCommandClient asyncCmdClientHelper =
new AsyncCommandClient(session, null);
asyncCmdClientHelper.execute(cmd);
CommandResult result = cmd.getCommandResult();
if (result.isSuccessful()) {
System.out.println("Successfully executed the command");
System.out.println("Result: ");
Object resultData = result.getResult();
if (resultData instanceof Object[]) {
Object[] resDataArr = (Object[])resultData;
for (Object resData : resDataArr) {
System.out.println(resData);
}
} else {
System.out.println(resultData);
}
} else {
System.out.println("Failed to execute the command");
result.getException().printStackTrace();
}
Documentation Link : https://www.ibm.com/developerworks/websphere/techjournal/1303_samantary/1303_samantary.html

How to do naming system with RMI in different hosts?

I have two java classes one is the client and the other is the server, in the client I have to give the server ip address, but I want to make it dynamique so the client knows the ip of a third machine(naming system) which search for the method (like DNS) and returns the ip address of the specific server who provides this method.
Edited:
classe client :
public class Client {
private Client() {}
public static void main(String[] args) {
String host = (args.length < 1) ? null : args[0];
try {
//Registry registry = LocateRegistry.getRegistry(host);
Registry registry = LocateRegistry.getRegistry("192.168.1.9",1091);
Calculator stub = (Calculator) registry.lookup("Hello");
String response = stub.add(4,2);
System.out.println("response: " + response);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
server :
public class Server implements Calculator{
public Server() {}
public String add(int a,int b) {
return "Hello, a+b= "+(a+b);
}
public String sub(int a,int b) {
return "Hello, a-b= "+(a-b);
}
public static void main(String args[]) {
try {
Server obj = new Server();
Calculator stub = (Calculator) UnicastRemoteObject.exportObject(obj, 0);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(1091);
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
You can't do this with the RMI Registry. Only a process running in the same host as the Registry can bind to it. You would have to use a different naming service such as LDAP.
However the rest of your description is what RMI already does. You look up a name in the Registry and it returns you a stub that knows how to communicate with the corresponding remote object.

Is it possible to synchronize two threads over shared Remote Object?

public class RMIClient {
public static void main(String[] args) {
String serverURL = "rmi://" + args[0] + "/GameServer";
String viewURL = "rmi://" + args[0] + "/ViewServer";
try {
GameInterface gameIntf = (GameInterface)Naming.lookup(serverURL);
PlayerView view = (PlayerView)Naming.lookup(viewURL);
while(!gameIntf.getGameOver()){
synchronized(GameInterface.sharedObject){
GameInterface.sharedObject.notify();
System.out.println(view.getMessage());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
if(br.readLine().contains("y"))
gameIntf.setNextMove(true);
GameInterface.sharedObject.wait();
}
}
} catch (MalformedURLException | RemoteException | NotBoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public interface GameInterface extends Remote{
public static final Object sharedObject = new Object();
public void setNextMove(boolean val) throws RemoteException;
public boolean getGameOver() throws RemoteException;
}
Currently when I start rmiregistry, server and start two RMI clients, both clients wait forever after getting 1st input i. e. one client is not notifying other. I am starting RMI clients on same JVM.
No. The stub object at the client is not the same Java object as the remote server in the server host, and synchronizing on it or notifying it doesn't magically propagate across the network to the server or to other clients.
The answers in the link you cited don't support your theory either. You need to read the answers by #MarcH and me, and ignore the others, which are wrong in various ways.

Retrieve GPS DATA on a JTextArea with 2 different class

I have a a GPS receptor. I create a class to retrieve all the GPS data on my Eclipse Console.
(This is the code of makia42)
public class COM implements Runnable{
static Thread myThread=null;
static BufferedReader br;
static BufferedWriter wr;
static InputStreamReader isr;
static OutputStreamWriter osw;
static java.io.RandomAccessFile port;
public COM(){ /**Constructeur*/
myThread=new Thread(this);
}
public void start(){
try {
port=new java.io.RandomAccessFile("COM3","rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
}
catch (Exception e) {
System.out.println("start "+e.toString());
}
myThread.start();
}
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
public static void main(String[] args) {
COM temp= new COM();
temp.start();
}
}
I have another class which is a frame containing a button and a JTextArea. This class is in communication with my first class COM.
When i click the button, COM is starting and show me the data in my Eclipse Console.
But now, I'd like to show it on my JTextArea.
How can I do it ?
Best regards,
Tofuw
Take a moment to read about this pattern.
Make the Thread a Subject. Before starting register the instance of the class that contains the JTextArea as the Observer with the instance of the Thread. At the run() instead of printing on the console, use the notify(String);
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
System.out.println(st);
}
}
Change to
public void run() {
System.out.println("lecture COM...");
for(;;){
String st = null;
try {
st=port.readLine();
} catch (IOException e) {System.out.println(e.getMessage());}
notifyObservers(st); //Pass the data to the observers.
}
}
EDIT:
I suppose you can rewrite the Thread to a simple class. It will render the program unresponsive while it reads, that's why you have a Thread. I suppose you can implement a cleaner way using Future<String>
public class GpsReader {
public class GenericGPSException extends Exception {
public GenericGPSException(String message, Throwable cause) {
super(message, cause);
}
}
public static void main(String[] args) {
// Example of usage
GpsReader gpsReader = new GpsReader();
String messageFromDevice;
try {
// Try read it
messageFromDevice = gpsReader.getCoordinate();
} catch (GenericGPSException e) {
// Error, what does it says?
messageFromDevice = e.getMessage();
}
JTextArea mockArea = new JTextArea();
// Show to user anything that comes to it.
mockArea.setText(messageFromDevice);
}
private boolean isReady;
private RandomAccessFile port;
public GpsReader() {
}
public String getCoordinate() throws GenericGPSException {
if (!isReady) {
try {
port = new RandomAccessFile("COM3", "rwd");
port.writeBytes("\r\n");
port.writeBytes("c,31,0,0,5\r\n");
port.writeBytes("T,1000,1\r\n");
isReady = true;
} catch (FileNotFoundException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
} catch (IOException e) {
throw new GenericGPSException(
"Error at starting communication to Device ", e);
}
}
try {
return port.readLine();
} catch (IOException e) {
throw new GenericGPSException("Error at reading the Device ", e);
}
}
}

no such object in table when calling registry.lookup

i am having a trouble when trying to run communication between server and client using RMI. My code is attached below. Server runs fine, i can see listening port in list of pc ports, client fails on registry.lookup. I didnt find any similar problem. Please help.
Server:
public class Main {
private static int port = Registry.REGISTRY_PORT;
private static Registry registry;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
if (args.length == 1) {
try {
port = Integer.parseInt(args[0]);
}
catch (NumberFormatException e) {
System.out.println("Port number is not valid!");
System.exit(0);
}
}
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
String name = "DBInterface";
System.out.println("Starting server.");
try {
DBInterface DBInterface = new DBClass();
DBInterface stub = (DBInterface) UnicastRemoteObject.exportObject(DBInterface, 5000);
registry = LocateRegistry.createRegistry(port);
registry.rebind(name, stub);
}
catch (RemoteException e)
{
System.out.println(e.getMessage());
}
System.out.println("Server succesfully started.");
}
}
Client:
public class Client {
private static String ipAddress = "localhost";
private static int port = Registry.REGISTRY_PORT;
private static String confFile = "";
public static DBInterface dbServer = null;
public static String name = "DBInterface";
public static void main(String[] args) {
System.out.println("Starting client.");
if (System.getSecurityManager() == null)
System.setSecurityManager(new RMISecurityManager());
if (args.length == 3) {
try {
ipAddress = args[0];
port = Integer.parseInt(args[1]);
confFile = args[2];
}
catch (NumberFormatException e) {
System.out.println("Port number is not valid!");
System.exit(0);
}
}
else
{
System.out.println("Some parameter is missing!");
System.out.println("Valid parameters are: IP(0) Port(1) Config_file_name(2).");
}
ArrayList<ArrayList<String>> commands = Tools.loadConfigFile(confFile);
Iterator<ArrayList<String>> commandsIterator = commands.iterator();
Registry registry;
try {
registry = LocateRegistry.getRegistry(ipAddress, port);
dbServer = (DBInterface) registry.lookup(name); //code fails here
} catch (RemoteException e) {
System.out.println(e.getMessage()); //"no such object in table" is printed on the screen
} catch (NotBoundException e) {
System.out.println(e.getMessage());
}
Tools tools = new Tools(dbServer);
...
What you describe is basically impossible. That exception means that the stub you are using, in this case a Registry, no longer refers to a live exported object in the target JVM. However as Registry stubs are created locally there is no opportunity for them to expire at all. The only mechanism would be the Registry you created exiting, but the static Registry reference should prevent that.
I would change a few things though:
DBInterface stub = (DBInterface) UnicastRemoteObject.exportObject(DBInterface, 5000);
registry = LocateRegistry.createRegistry(port);
Reverse these two lines, and use port for both the Registry and the export. You don't need two ports. Also, in all your catch blocks, never just suppress the exception message in favour of your own. You should always at least log the actual exception message.

Categories

Resources