美文网首页
chrome 插件实现mac地址获取

chrome 插件实现mac地址获取

作者: 3c69b7c624d9 | 来源:发表于2017-11-30 02:03 被阅读1859次

    浏览器无法通过js获取到硬件信息众所周知,ie是也是通过ActiveX来完成的。

    由于我们一直使用Chrome,因此考虑开发chrome插件。

    普通chrome插件也是无法获取到mac地址等信息的,我们采取和本地通信app的实现。

    1. 准备宿主端,我们称之为host

    2. 准备插件端,我们称之为extension 121912_l1si_871390.png121912_l1si_871390.png

      如上图所示,我们通过插件端和host进行通信,插件也可以通过授权来访问 指定的页面的document。在进行指定编码格式约定后就可以进行我们的编码了。

      对于chrome的插件开发我们就不说了,可以在网络上抄到一堆。

      插件开发

      manifest

          {
            "name": "F6养车PC版安全插件",
            "version": "1.0",
            "manifest_version": 2,
            "description": "使用本插件实现从指定PC登录系统",
            "background": {
              "scripts": [
                "background.js"
              ]
            },
            "icons": {
              "128": "icon-128.png"
            },
            "browser_action": {
              "default_icon": "icon-19.png",
              "default_title": "F6养车PC版安全插件"
            },
            "homepage_url": "http://m.f6car.com",
            "content_scripts": [
              {
                "matches": [
                  "http://*/*"
                ],
                "js": [
                  "content.js"
                ],
                "run_at": "document_end"
              }
            ],
            "externally_connectable": {
              "matches": [
                "http://*.f6car.com/*",
                "http://localhost:9001/*",
                "http://127.0.0.1:9001/*",
                "http://192.168.1.153:9001/*",
                "http://192.168.1.19:9001/*"
              ]
            },
            "permissions": [
              "nativeMessaging",
              "tabs",
              "http://*/*",
              "https://*/*"
            ]
          }
      

      content.js

      对应后需要增加content.js 负责和页面dom交互

          chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
              console.debug("chrome.runtime.onMessage called");
              if (!!request.text) {
                  console.debug("mac address:%s", request.text);
                  var macEle = document.getElementById("mac");
                  if (!!macEle) {
                      macEle.value = request.text
                  }
              }
          });
      

      brankground.js

      增加和host通信的background.js

          var port = null;
          var hostName = "com.f6car.chrome.safe.echo";
          var mac = {};
          function connect() {
              port = chrome.runtime.connectNative(hostName);
              port.onMessage.addListener(onNativeMessage);
              port.onDisconnect.addListener(onDisconnected);
          }
           
          function onNativeMessage(message) {
              console.debug("nativemessage:%s",JSON.stringify(message));
              chrome.tabs.query({active: true}, function (tabs) {
                  console.debug("tabs:%s",JSON.stringify(tabs));
                  chrome.tabs.sendMessage(tabs[0].id, message, function (response) {
                      console.debug("baground  respone");
                  });
              });
           
          }
           
          function onDisconnected() {
              port = null;
          }
           
          chrome.runtime.onMessageExternal.addListener(
              function (request, sender, sendResponse) {
                  if (request.requestType === "connect") {
                      if (port === null) {
                          connect();
                      }
                  }
                  else {
                      if (port === null) {
                          connect();
                      }
                      else {
                          if (!!mac.text) {
                              sendResponse(mac);
                          }
                      }
                  }
              });
      

      host开发

      权限配置

      windows

          {
            "name": "com.f6car.chrome.safe.echo",
            "description": "F6养车PC版安全插件HOST",
            "path": "f6Safe.exe",
            "type": "stdio",
            "allowed_origins": [
              "chrome-extension://fndijacmgfpgicgknoceclheehanolhc/"
            ]
          }
      

      Mac/Linux

          {
            "name": "com.f6car.chrome.safe.echo",
            "description": "F6养车PC版安全插件HOST",
            "path": "HOST_PATH",
            "type": "stdio",
            "allowed_origins": [
              "chrome-extension://fndijacmgfpgicgknoceclheehanolhc/"
            ]
          }
      

      host编写

      windows

          #include <stdio.h>
          #include <windows.h>
          #include <string>
          #include <Assert.h>
          #include <iphlpapi.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <cstdlib>
          #include <unistd.h>
          #include <iostream>
           
           
          #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
           
           
          static std::string GetMACaddress(void)
          {
          IP_ADAPTER_INFO AdapterInfo[16];
          // Allocate information for up to 16 NICs
          DWORD dwBufLen = sizeof(AdapterInfo);
          // Save the memory size of buffer
           
           
          DWORD dwStatus = GetAdaptersInfo(
          // Call GetAdapterInfo
          AdapterInfo,  // [out] buffer to receive data
          &dwBufLen);  // [in] size of receive data buffer
          assert(dwStatus == ERROR_SUCCESS);
          // Verify return value is valid, no buffer overflow
           
           
          PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info
          std::string outMsg = "";
          do {
          char acMAC[32];
          sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",
          int (pAdapterInfo->Address[0]),
          int (pAdapterInfo->Address[1]),
          int (pAdapterInfo->Address[2]),
          int (pAdapterInfo->Address[3]),
          int (pAdapterInfo->Address[4]),
          int (pAdapterInfo->Address[5]));
          outMsg.append(acMAC);
          outMsg.append(",");
          pAdapterInfo = pAdapterInfo->Next;
          // Progress through linked list
          }
          while(pAdapterInfo);
          if(outMsg.length()>5){
          outMsg = outMsg.substr(0,outMsg.length()-1);
          }
              return outMsg;
          }
           
           
          int main(int argc, _TCHAR* argv[]){
           std::string outMsg = "{\"text\":\""+GetMACaddress()+"\"}";
           unsigned int outLen = outMsg.length();
           char *bOutLen = reinterpret_cast<char *>(&outLen);
           std::cout.write(bOutLen, 4);
           std::cout << outMsg << std::flush;
           return 0;
          }
          ```
      
      ####      Mac/Linux ####
      ```python
          #!/usr/bin/env python
          # Copyright (c) 2012 The Chromium Authors. All rights reserved.
          # Use of this source code is governed by a BSD-style license that can be
          # found in the LICENSE file.
           
          # A simple native messaging host. Shows a Tkinter dialog with incoming messages
          # that also allows to send message back to the webapp.
           
          import Queue
          import struct
          import sys
          import threading
           
          try:
              import Tkinter
              import tkMessageBox
          except ImportError:
              Tkinter = None
           
          # On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY
          # to avoid unwanted modifications of the input/output streams.
          if sys.platform == "win32":
              import os, msvcrt
           
              msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
              msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
           
           
          # Helper function that sends a message to the webapp.
          def send_message(message):
              # Write message size.
              sys.stdout.write(struct.pack('I', len(message)))
              # Write the message itself.
              sys.stdout.write(message)
              sys.stdout.flush()
           
           
          # Thread that reads messages from the webapp.
          def read_thread_func(queue):
              message_number = 0
              while 1:
                  # Read the message length (first 4 bytes).
                  text_length_bytes = sys.stdin.read(4)
           
                  if len(text_length_bytes) == 0:
                      if queue:
                          queue.put(None)
                      sys.exit(0)
           
                  # Unpack message length as 4 byte integer.
                  text_length = struct.unpack('i', text_length_bytes)[0]
           
                  # Read the text (JSON object) of the message.
                  text = sys.stdin.read(text_length).decode('utf-8')
           
                  if queue:
                      queue.put(text)
                  else:
                      # In headless mode just send an echo message back.
                      send_message('{"echo": %s}' % text)
           
           
          if Tkinter:
              class NativeMessagingWindow(Tkinter.Frame):
                  def __init__(self, queue):
                      self.queue = queue
           
                      Tkinter.Frame.__init__(self)
                      self.pack()
           
                      self.text = Tkinter.Text(self)
                      self.text.grid(row=0, column=0, padx=10, pady=10, columnspan=2)
                      self.text.config(state=Tkinter.DISABLED, height=10, width=40)
           
                      self.messageContent = Tkinter.StringVar()
                      self.sendEntry = Tkinter.Entry(self, textvariable=self.messageContent)
                      self.sendEntry.grid(row=1, column=0, padx=10, pady=10)
           
                      self.sendButton = Tkinter.Button(self, text="Send", command=self.onSend)
                      self.sendButton.grid(row=1, column=1, padx=10, pady=10)
           
                      self.after(100, self.processMessages)
           
                  def processMessages(self):
                      while not self.queue.empty():
                          message = self.queue.get_nowait()
                          if message == None:
                              self.quit()
                              return
                          self.log("Received %s" % message)
           
                      self.after(100, self.processMessages)
           
                  def onSend(self):
                      text = '{"text": "' + self.messageContent.get() + '"}'
                      self.log('Sending %s' % text)
                      try:
                          send_message(text)
                      except IOError:
                          tkMessageBox.showinfo('Native Messaging Example',
                                                'Failed to send message.')
                          sys.exit(1)
           
                  def log(self, message):
                      self.text.config(state=Tkinter.NORMAL)
                      self.text.insert(Tkinter.END, message + "\n")
                      self.text.config(state=Tkinter.DISABLED)
           
           
          def Main():
              if not Tkinter:
                  send_message('"Tkinter python module wasn\'t found. Running in headless ' +
                               'mode. Please consider installing Tkinter."')
                  read_thread_func(None)
                  sys.exit(0)
           
              queue = Queue.Queue()
           
              main_window = NativeMessagingWindow(queue)
              main_window.master.title('Native Messaging Example')
           
              thread = threading.Thread(target=read_thread_func, args=(queue,))
              thread.daemon = True
              thread.start()
           
              main_window.mainloop()
           
              sys.exit(0)
          def get_mac_address():
              import sys
              import os
              mac = None
              if sys.platform == "win32":
                  for line in os.popen("ipconfig /all"):
                      print line
                      if line.lstrip().startswith("Physical Address"):
                          mac = line.split(":")[1].strip().replace("-", ":")
                          break
              else:
                  for line in os.popen("/sbin/ifconfig"):
                      if 'Ether' in line or 'ether' in line :
                          mac = line.split()[1].replace(":","-")
                          break
              return mac
          def get_json(message):
              return '{"text": "' +message+ '"}'
          if __name__ == '__main__':
              send_message (get_json(get_mac_address()))
      

      安装脚本

      windows

          :: Copyright 2014 The Chromium Authors. All rights reserved.
          :: Use of this source code is governed by a BSD-style license that can be
          :: found in the LICENSE file.
           
          :: Change HKCU to HKLM if you want to install globally.
          :: %~dp0 is the directory containing this bat script and ends with a backslash.
          REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.f6car.chrome.safe.echo" /ve /t REG_SZ /d "%~dp0com.f6car.chrome.safe.echo-win.json" /f
      

      Mac/Linux

          #!/bin/sh
          # Copyright 2013 The Chromium Authors. All rights reserved.
          # Use of this source code is governed by a BSD-style license that can be
          # found in the LICENSE file.
           
          set -e
           
          DIR="$( cd "$( dirname "$0" )" && pwd )"
          if [ "$(uname -s)" = "Darwin" ]; then
            if [ "$(whoami)" = "root" ]; then
              TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"
            else
              TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
            fi
          else
            if [ "$(whoami)" = "root" ]; then
              TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"
            else
              TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts"
            fi
          fi
           
          HOST_NAME=com.f6car.chrome.safe.echo
           
          # Create directory to store native messaging host.
          mkdir -p "$TARGET_DIR"
           
          # Copy native messaging host manifest.
          sudo cp "$DIR/$HOST_NAME.json" "$TARGET_DIR"
           
          # Update host path in the manifest.
          HOST_PATH=$DIR/$HOST_NAME
          ESCAPED_HOST_PATH=${HOST_PATH////\\/}
          sudo sed -i -e "s/HOST_PATH/$ESCAPED_HOST_PATH/" "$TARGET_DIR/$HOST_NAME.json"
           
          # Set permissions for the manifest so that all users can read it.
          sudo chmod o+r "$TARGET_DIR/$HOST_NAME.json"
           
          echo "Native messaging host $HOST_NAME has been installed."
      

      以上完成代码编写,打包即可

    参考资料:

    http://blog.csdn.net/zhangjs712/article/details/50913114

    https://developer.chrome.com/extensions/crx

    http://bbs.360.cn/forum.php?mod=viewthread&tid=15079033 (本人就兼容性问题在360浏览器无法安装)

    http://open.se.360.cn/open/extension_dev/overview.html

    http://blog.csdn.net/talking12391239/article/details/38498557

    https://developer.chrome.com/extensions/nativeMessaging

    具体代码可以查看 码云 http://git.oschina.net/qixiaobo/chromeMacGetter

    相关文章

      网友评论

          本文标题:chrome 插件实现mac地址获取

          本文链接:https://www.haomeiwen.com/subject/unymbxtx.html