×

JavaWEB获取客户端IP,主机名,Mac地址等等方案

我的笔记 我的笔记 发表于2018-08-07 15:13:09 浏览2553 评论0

抢沙发发表评论


一、这个类是获取操作系统相关信息,包括操作系统版本,真实ip,浏览器版本,这个类中的获取mac地址较慢,建议使用第二种,大部分方式是从HttpServletRequest中即可获取。


import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.InputStreamReader;

public class ClientOS{
    /****
     * 获取操作系统
     * @param userAgent
     * @return
     */
    public static String getClientOS(String userAgent){
        String cos = "unknow os";

        Pattern p = Pattern.compile(".*(Windows NT 10).*");
        Matcher m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Win 10";
            return cos;
        }

        p = Pattern.compile(".*(Windows NT 6\\.1).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Win 7";
            return cos;
        }

        p = Pattern.compile(".*(Windows NT 5\\.1|Windows XP).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "WinXP";
            return cos;
        }

        p = Pattern.compile(".*(Windows NT 5\\.2).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Win2003";
            return cos;
        }

        p = Pattern.compile(".*(Win2000|Windows 2000|Windows NT 5\\.0).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Win2000";
            return cos;
        }

        p = Pattern.compile(".*(Mac|apple|MacOS8).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "MAC";
            return cos;
        }

        p = Pattern.compile(".*(WinNT|Windows NT).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "WinNT";
            return cos;
        }

        p = Pattern.compile(".*Linux.*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Linux";
            return cos;
        }

        p = Pattern.compile(".*(68k|68000).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Mac68k";
            return cos;
        }

        p = Pattern.compile(".*(9x 4.90|Win9(5|8)|Windows 9(5|8)|95/NT|Win32|32bit).*");
        m = p.matcher(userAgent);
        if(m.find())
        {
            cos = "Win9x";
            return cos;
        }

        return cos;
    }

    /***
     * 获取真实ip
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request){
        String ipAddress = request.getHeader("x-forwarded-for");
         if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
         }
         if (ipAddress == null || ipAddress.length() == 0 || "unknow".equalsIgnoreCase(ipAddress)) {
                 ipAddress = request.getHeader("WL-Proxy-Client-IP");
         }
         if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
              ipAddress = request.getRemoteAddr();
              if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
                         //根据网卡获取本机配置的IP地址
                       InetAddress inetAddress = null;
                       try {
                                inetAddress = InetAddress.getLocalHost();
                       } catch (UnknownHostException e) {
                                 e.printStackTrace();
                             }
                         ipAddress = inetAddress.getHostAddress();
                    }
             }
         //对于通过多个代理的情况,第一个IP为客户端真实的IP地址,多个IP按照','分割
        if(null != ipAddress && ipAddress.length() > 15){
               //"***.***.***.***".length() = 15
                 if(ipAddress.indexOf(",") > 0){
                     ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                 }
         }
         return ipAddress;
     }
    /**
     * 获取来访者的浏览器版本
     * @param request
     * @return
     */
    public static String getRequestBrowserInfo(HttpServletRequest request){
        String browserVersion = null;
        String header = request.getHeader("user-agent");
        if(header == null || header.equals("")){
            return "";
        }
        if(header.indexOf("MSIE")>0){
            browserVersion = "IE";
        }else if(header.indexOf("Firefox")>0){
            browserVersion = "Firefox";
        }else if(header.indexOf("Chrome")>0){
            browserVersion = "Chrome";
        }else if(header.indexOf("Safari")>0){
            browserVersion = "Safari";
        }else if(header.indexOf("Camino")>0){
            browserVersion = "Camino";
        }else if(header.indexOf("Konqueror")>0){
            browserVersion = "Konqueror";
        }
        return browserVersion;
    }
    /**
     * 获取来访者的主机名称
     * @param ip
     * @return
     */
    public static String getHostName(String ip){
        InetAddress inet;
        try {
            inet = InetAddress.getByName(ip);
            return inet.getHostName();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 命令获取mac地址
     * @param cmd
     * @return
     */
    private static String callCmd(String[] cmd) {
        String result = "";
        String line = "";
        try {
            Process proc = Runtime.getRuntime().exec(cmd);
            InputStreamReader is = new InputStreamReader(proc.getInputStream());
            BufferedReader br = new BufferedReader (is);
            while ((line = br.readLine ()) != null) {
                result += line;
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
     *
     *
     *
     * @param cmd
     *            第一个命令
     *
     * @param another
     *            第二个命令
     *
     * @return 第二个命令的执行结果
     *
     */

    private static String callCmd(String[] cmd,String[] another) {
        String result = "";
        String line = "";
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(cmd);
            proc.waitFor(); // 已经执行完第一个命令,准备执行第二个命令
            proc = rt.exec(another);
            InputStreamReader is = new InputStreamReader(proc.getInputStream());
            BufferedReader br = new BufferedReader (is);
            while ((line = br.readLine ()) != null) {
                result += line;
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     *
     *
     *
     * @param ip
     *            目标ip,一般在局域网内
     *
     * @param sourceString
     *            命令处理的结果字符串
     *
     * @param macSeparator
     *            mac分隔符号
     *
     * @return mac地址,用上面的分隔符号表示
     *
     */

    private static String filterMacAddress(final String ip, final String sourceString,final String macSeparator) {
        String result = "";
        String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";
        Pattern pattern = Pattern.compile(regExp);
        Matcher matcher = pattern.matcher(sourceString);
        while(matcher.find()){
            result = matcher.group(1);
            if(sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))) {
                break; // 如果有多个IP,只匹配本IP对应的Mac.
            }
        }
        return result;
    }

    /**
     * @param ip
     *            目标ip
     * @return Mac Address
     *
     */

    private static String getMacInWindows(final String ip){
        String result = "";
        String[] cmd = {"cmd","/c","ping " + ip};
        String[] another = {"cmd","/c","arp -a"};
        String cmdResult = callCmd(cmd,another);
        result = filterMacAddress(ip,cmdResult,"-");
        return result;
    }
    /**
     *
     * @param ip
     *            目标ip
     * @return Mac Address
     *
     */
    private static String getMacInLinux(final String ip){
        String result = "";
        String[] cmd = {"/bin/sh","-c","ping " +  ip + " -c 2 && arp -a" };
        String cmdResult = callCmd(cmd);
        result = filterMacAddress(ip,cmdResult,":");
        return result;
    }

    /**
     * 获取MAC地址
     *
     * @return 返回MAC地址
     */
    public static String getMacAddress(String ip){
        String macAddress = "";
        macAddress = getMacInWindows(ip).trim();
        if(macAddress==null||"".equals(macAddress)){
            macAddress = getMacInLinux(ip).trim();
        }
        return macAddress;
    }
}


二、这个类是获取网卡的mac地址,是通过向客户端发送一个UDP询问包,然后解析返回数据。,采用137端口。


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.concurrent.*;

/**
 * 主机A向主机B发送“UDP-NetBIOS-NS”询问包,即向主机B的137端口,发Query包来询问主机B的NetBIOS Names信息。
 * 其次,主机B接收到“UDP-NetBIOS-NS”询问包,假设主机B正确安装了NetBIOS服务........... 而且137端口开放,则主机B会向主机A发送一个“UDP-NetBIOS-NS”应答包,即发Answer包给主机A。
 * 并利用UDP(NetBIOS Name Service)来快速获取远程主机MAC地址的方法
 * 用法 :new UdpGetClientMacAddr(ip地址)
 * @author WINDY
 */

public class UdpGetClientMacAddr {
    private String sRemoteAddr;
    private int iRemotePort=137;
    private byte[] buffer = new byte[1024];
    private DatagramSocket ds=null;
    final ExecutorService exec = Executors.newFixedThreadPool(1);
    DatagramPacket dp=null;
    public UdpGetClientMacAddr(String strAddr) throws  Exception{
        sRemoteAddr = strAddr;
        ds = new DatagramSocket();
    }

    protected final DatagramPacket send(final byte[] bytes) throws IOException {
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,InetAddress.getByName(sRemoteAddr),iRemotePort);
        ds.send(dp);
        return dp;
    }

    protected final DatagramPacket receive() throws Exception {
        dp = new DatagramPacket(buffer,buffer.length);
        ds.receive(dp);
        return dp;
    }
    // 询问包结构:
    // Transaction ID 两字节(16位) 0x00 0x00
    // Flags 两字节(16位) 0x00 0x10
    // Questions 两字节(16位) 0x00 0x01
    // AnswerRRs 两字节(16位) 0x00 0x00
    // AuthorityRRs 两字节(16位) 0x00 0x00
    // AdditionalRRs 两字节(16位) 0x00 0x00
    // Name:array [1..34] 0x20 0x43 0x4B 0x41(30个) 0x00 ;
    // Type:NBSTAT 两字节 0x00 0x21
    // Class:INET 两字节(16位)0x00 0x01
    protected byte[] GetQueryCmd() throws Exception {
        byte[] t_ns = new byte[50];
        t_ns[0] = 0x00;
        t_ns[1] = 0x00;
        t_ns[2] = 0x00;
        t_ns[3] = 0x10;
        t_ns[4] = 0x00;
        t_ns[5] = 0x01;
        t_ns[6] = 0x00;
        t_ns[7] = 0x00;
        t_ns[8] = 0x00;
        t_ns[9] = 0x00;
        t_ns[10] = 0x00;
        t_ns[11] = 0x00;
        t_ns[12] = 0x20;
        t_ns[13] = 0x43;
        t_ns[14] = 0x4B;

        for(int i = 15; i < 45; i++)
        {
            t_ns[i] = 0x41;
        }

        t_ns[45] = 0x00;
        t_ns[46] = 0x00;
        t_ns[47] = 0x21;
        t_ns[48] = 0x00;
        t_ns[49] = 0x01;
        return t_ns;
    }
    // 表1 “UDP-NetBIOS-NS”应答包的结构及主要字段一览表
    // 序号 字段名 长度
    // 1 Transaction ID 两字节(16位)
    // 2 Flags 两字节(16位)
    // 3 Questions 两字节(16位)
    // 4 AnswerRRs 两字节(16位)
    // 5 AuthorityRRs 两字节(16位)
    // 6 AdditionalRRs 两字节(16位)
    // 7 Name<Workstation/Redirector> 34字节(272位)
    // 8 Type:NBSTAT 两字节(16位)
    // 9 Class:INET 两字节(16位)
    // 10 Time To Live 四字节(32位)
    // 11 Length 两字节(16位)
    // 12 Number of name 一个字节(8位)
    // NetBIOS Name Info 18×Number Of Name字节
    // Unit ID 6字节(48位
    protected final String GetMacAddr(byte[] brevdata) throws Exception {
        // 获取计算机名
        int i = brevdata[56] * 18 + 56;
        String sAddr="";
        StringBuffer sb = new StringBuffer(17);
        // 先从第56字节位置,读出Number Of Names(NetBIOS名字的个数,其中每个NetBIOS Names Info部分占18个字节)
        // 然后可计算出“Unit ID”字段的位置=56+Number Of Names×18,最后从该位置起连续读取6个字节,就是目的主机的MAC地址。
        for(int j = 1; j < 7;j++)
        {
            sAddr = Integer.toHexString(0xFF & brevdata[i+j]);
            if(sAddr.length() < 2)
            {
                sb.append(0);
            }
            sb.append(sAddr.toUpperCase());
            if(j < 6) sb.append(':');
        }
        return sb.toString();
    }

    public final void close() {
        try
        {
            ds.close();
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
    }

    public final String GetRemoteMacAddr() {
        String smac = null;
        try {
            byte[] bqcmd = GetQueryCmd();
            send(bqcmd);
            //DatagramPacket dp = receive();
            Future<DatagramPacket> future = exec.submit(call);
            DatagramPacket dp = future.get(1000 * 1, TimeUnit.MILLISECONDS);
            smac = GetMacAddr(dp.getData());
            close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return smac;
    }
    Callable<DatagramPacket> call = new Callable<DatagramPacket>() {
        public DatagramPacket call() throws Exception {
            //开始执行耗时操作
            return receive();
        }
    };
}


我的笔记博客版权我的笔记博客版权