Applet para buscar MAC, não funciona no Java 1.6.0_22

7 respostas
J

Eu tenho um sistema web que utiliza um applet para validação de clientes, no qual ele efetua o cadastro da maquina e obtem como um dos itens de verificação o Mac Address.

Tenho esse sistema implementado a aproximadamente 1 ano já, e até a versão 1.6.0_21 do Java ele funcionava.
Essa ultima atualização (Java 1.6.0_22) que começou a me causar problemas.

Ele obtem qualquer informação, mas somente a função getHardwareAddress() me traz o valor null.

Eu tenho o seguinte codigo:

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.applet.Applet;

import javax.swing.JOptionPane;
import netscape.javascript.JSObject;

public class Mac extends Applet {

	public void init(){

		String MaquinaSHA1 = null;
		Enumeration en = null;
		String aMaquinaSHA1 = null;
		String sMensagemERRO =  "Não foi possivel efetuar a verificação da estação de trabalho!\n" +
								"Motivo: A versão do Java não é compativel!\n" +
								"Versão requerida: Java 1.6+";

        try {
            //captura as interfaces de rede da máquina
            en = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException ex) {
        	JOptionPane.showMessageDialog(null, sMensagemERRO + 
        			"\n\nERRO: (01) Não foi possivel obter informações do computador!", "Sistema XXX", JOptionPane.ERROR_MESSAGE);
        	ex.printStackTrace();
        }

        //instancia um objeto interfa de rede
        while (en.hasMoreElements()){
            NetworkInterface ni = (NetworkInterface) en.nextElement();

	        // busca todas as informacoes da interface de rede
	        String enderecoMac = null;

	        //codigo para pegar o mac address
	        //instancia um array de byte
	        byte[] bytes = null;
	        try {
	            //pega o codigo em bytes
	            bytes = ni.getHardwareAddress();
	        } catch (SocketException ex) {
	        	JOptionPane.showMessageDialog(null, sMensagemERRO + 
	        			"\n\nERRO: (02) Não foi possivel obter informações do computador!", "Sistema XXX", JOptionPane.ERROR_MESSAGE);
	        	ex.printStackTrace();
	        }
	        //variavel auxiliar na transformacao de byte para hexa
	        StringBuilder aux = new StringBuilder();
	        
	        if (bytes != null){
		        //laco para converter os bytes em hexa
	            for (int i = 0; i < bytes.length; i++) {
	                int parteAlta = ((bytes[i] >> 4) & 0xf) << 4;
	                int parteBaixa = bytes[i] & 0xf;

	                if (parteAlta == 0) {
	                    aux.append('0');
	                }
	                //adiciona a aux o codigo referente o bytes[i]
	                aux.append(Integer.toHexString(parteAlta | parteBaixa));
	            }
	            
	            //Pega a MAC joga em uma variavel como string
	            enderecoMac = aux.toString();
	            
	            if ((enderecoMac != "") && (enderecoMac.length() == 12)){
		            // Gera a Chave com o SHA1, com todos os dados da maquina
		            try {
		            	MaquinaSHA1 = SHA1(enderecoMac);
		            } catch (NoSuchAlgorithmException e) {
			        	JOptionPane.showMessageDialog(null, sMensagemERRO + 
			        			"\n\nERRO: (03) Não foi possivel criptografar as informações!", "Sistema XXX", JOptionPane.ERROR_MESSAGE);
			        	e.printStackTrace();
					} catch (UnsupportedEncodingException e) {
			        	JOptionPane.showMessageDialog(null, sMensagemERRO + 
			        			"\n\nERRO: (04) Não foi possivel criptografar as informações!", "Sistema XXX", JOptionPane.ERROR_MESSAGE);
			        	e.printStackTrace();
					}
	
					// Joga todas as MAC em um array
					if (aMaquinaSHA1 != ""){
						aMaquinaSHA1 = aMaquinaSHA1 + "," + MaquinaSHA1;
					}else{
						aMaquinaSHA1 = MaquinaSHA1;
					}
	            }
	        }
        }

        if ((aMaquinaSHA1 == null) || (aMaquinaSHA1 == "")){
        	JOptionPane.showMessageDialog(null, "ERRO: (05) Não foi possivel obter as informações do computador!", "Sistema XXX", JOptionPane.ERROR_MESSAGE);
        }else{
	        try {
	        	SetaDados(aMaquinaSHA1);
	        }catch (Exception e1){
		        try {
		        	//Chama a funcao java script da tela
		        	getAppletContext().showDocument(
		    				new URL("javascript:getMaquina('" + aMaquinaSHA1 +"')")
		    		);
		        }catch (MalformedURLException me){
					try {
						getAppletContext().showDocument(
									new URL("https://www.XXX.com.br/java/default.asp?openjdk=1&id=" + aMaquinaSHA1)
						);
					} catch (MalformedURLException e2) {
			        	JOptionPane.showMessageDialog(null, sMensagemERRO + 
			        			"\n\nERRO: (06) Não foi possivel enviar as informações!", "Sistema XXX", JOptionPane.ERROR_MESSAGE);
			        	e2.printStackTrace();
					}
		        }
	        }
        }
	}

    private static String convertToHex(byte[] data) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            int halfbyte = (data[i] >>> 4) & 0x0F;
            int two_halfs = 0;
            do {
                if ((0 <= halfbyte) && (halfbyte <= 9))
                    buf.append((char) ('0' + halfbyte));
                else
                    buf.append((char) ('a' + (halfbyte - 10)));
                halfbyte = data[i] & 0x0F;
            } while(two_halfs++ < 1);
        }
        return buf.toString();
    }
 
    public static String SHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException  {
    	MessageDigest md;
    	md = MessageDigest.getInstance("SHA-1");
    	byte[] sha1hash = new byte[40];
    	md.update(text.getBytes("iso-8859-1"), 0, text.length());
    	sha1hash = md.digest();
    	return convertToHex(sha1hash);
    }

    public void SetaDados(String sMac){
  	
		JSObject objWin = JSObject.getWindow(this);
		JSObject objDoc = (JSObject)objWin.getMember("document");
		JSObject objForms = (JSObject)objDoc.getMember("forms");
		JSObject objForm = (JSObject)objForms.getMember("form1");
		JSObject objElements = (JSObject)objForm.getMember("elements");
		JSObject campoDoFormularioHTML = (JSObject)objElements.getMember("txtChaveAcesso");
		campoDoFormularioHTML.setMember("value", sMac);
		objWin.call("sendMaquina", null);
    	
    }
}

Abraço!

7 Respostas

E

Também estou com o mesmo problema. Já estou até procurando alternativas ao applet.

KWill

Isto aqui explica bastante coisa.

Pelo jeito, aparentemente tu só pode fazer essa chamada dentro do “Applet.init()” se tu estiver usando Applets.
Eu mesmo ainda gosto de Applets, mas se tivermos que fazer esses malabarismos para manter as coisas funcionando melhor migrar logo as coisas para JWS.

EDITADO: Outras dicas: 6u22 Release Notes

Até mais.

E

Não funciona no init(). Já fiz o teste. Acabei de responder nesse mesmo forum.
Já tentei pedir por privilegios e até assinei o JAR mas não adiantou.

J

Pois é…

Ta complicada a coisa.

J

Para deixar funcionando o sistema, fiz um .jar para fazer o mesmo serviço.

O único problema é que não tem aquela facilidade do applet para o cliente.

Mas beleza!

E
Estou usando uma outra solução: ao invés de pegar o mac, gere um identificador único e grave na máquina do cliente. O applet precisa estar assinado.
import java.io.*;
import java.applet.*;
import java.util.UUID;

public class IDApplet extends Applet {
	static final String FILE_NAME = System.getProperty("user.home") + "/uid.dat";
	static String uid = null;
	
	public void init() {
		try {
			uid = readFromFile();
		}
		catch (Exception e) {
			uid = "Error: " + e.getMessage();
		}
	}

	public static String getID() {
		return uid;
	}
	private static String readFromFile() throws java.io.IOException {
		try {
			FileInputStream fin =  new FileInputStream(FILE_NAME);
			BufferedReader myInput = new BufferedReader (new InputStreamReader(fin));
			String firstLine = myInput.readLine();
			fin.close();
			return firstLine;
		}
		catch (Exception e) {
			String uid = UUID.randomUUID().toString();
			writeToFile(uid);
			return uid;
		}
	}
	private static void writeToFile(String uid) throws java.io.IOException {
		FileWriter fstream = new FileWriter(FILE_NAME);
		BufferedWriter out = new BufferedWriter(fstream);
		out.write(uid);
		out.close();
	}
}
E
Acabei de ver que realmente se colocar no init e o applet estiver assinado, dá para pegar o mac. Eu devo ter feito alguma coisa de errado no outro teste que fiz. Deve-se tomar cuidado porque costumam vir algumas placas sem mac então se vier um valor nulo não significa que não será possível pegar outros macs que ainda estão por vir. Isso serviu para melhorar a forma de identificar a máquina. Agora estou combinando o identificador único com os macs.
import java.io.*;
import java.applet.*;
import java.util.*;
import java.net.*;

public class IDApplet extends Applet {
	static final String FILE_NAME = System.getProperty("user.home") + "/uuid.dat";
	static String uuid = null;
	static String macs = null;
	
	public void init() {
		try {
			uuid = getUuidFromFile();
		}
		catch (Exception e) {
			uuid = "Error: " + e.getMessage();
		}
		macs = readMacs();
	}
	public static String getUuid() {
		return uuid;
	}
	public static String getMacs() {
		return macs;
	}
	private static String readMacs() {
		String ret = "";
		int macCount = 0;
        try {
            Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
            if (nis != null) {
                while (nis.hasMoreElements()) {
                    NetworkInterface currentNI = nis.nextElement();
                    Enumeration<InetAddress> addresses = currentNI.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress inetAddress = addresses.nextElement();
                        byte[] mac = currentNI.getHardwareAddress();
                        if (mac != null) {
							macCount++;
							if (macCount > 1) {
								ret += ";";
							}
							for (int i = 0; i < mac.length; i++) {
								ret += new java.util.Formatter().format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "");
							}
                        }
                    }
                }
            }
        }
		catch (SocketException e) {
            ret = "Error: " + e.getMessage();
        }
		if (ret.length() < 12) {
			ret = "ERROR: Addresses don't exist or is not accessible.";
		}
		return ret;
    }
	private static String getUuidFromFile() throws java.io.IOException {
		try {
			FileInputStream fin =  new FileInputStream(FILE_NAME);
			BufferedReader myInput = new BufferedReader (new InputStreamReader(fin));
			String firstLine = myInput.readLine();
			fin.close();
			return firstLine;
		}
		catch (Exception e) {
			String uuid = UUID.randomUUID().toString();
			writeUuidToFile(uuid);
			return uuid;
		}
	}
	private static void writeUuidToFile(String uuid) throws java.io.IOException {
		FileWriter fstream = new FileWriter(FILE_NAME);
		BufferedWriter out = new BufferedWriter(fstream);
		out.write(uuid);
		out.close();
	}
}
O html fica assim:
<script type="text/javascript">
//<![CDATA[
	document.write ('<applet codebase="." code="IDApplet.class" archive="IDAppletSigned.jar" width="0" height="0" name="IDApplet">'
					+ '   <param name="mayscript" value="true">'
					+ '   <param name="scriptable" value="true">'
					+ '</applet>');
	
	function init() {
		var uid = IDApplet.getUuid(); 
		var macs = IDApplet.getMacs(); 
		alert("Bem vindo. Seu identificador único é: " + uid + ".\n Seus macs são " + macs + ".");
	}
//]]>
</script>
<body onload="init()">
</body>
Criado 16 de outubro de 2010
Ultima resposta 29 de out. de 2010
Respostas 7
Participantes 3