2009-09-19 35 views
27

Có ai biết về bất kỳ tập lệnh/lớp trình tạo khóa API nào cho PHP không? Lớp nên có phương thức tạo, sẽ tạo ra một phương thức quan trọng và isValid(), để kiểm tra xem khóa có hợp lệ hay không.Trình tạo khóa API PHP

+1

Nếu bạn có thể cung cấp thêm thông tin về mục đích sử dụng, trả lời có thể đơn giản hơn một chút ... là các khóa được lưu trữ ở đâu đó - giống như một DB? có bất kỳ giao tiếp client/server nào không? –

+0

GUID có hoạt động không? – nilamo

+0

GUID giống như # 1 trong câu trả lời của tôi. Chúng tôi đã thử UUID. 34-char là quá lớn cho hương vị của chúng tôi. Có vẻ như "3B90E4C1-C4D4-D204-ECB3-0CDB0F0A2E50". Nếu bạn có thể chấp nhận điều đó, hãy tiếp tục. –

Trả lời

7

chỉ cần sử dụng một cái gì đó như thế này (mã giả) sha1(salt + time + mac-addr + another salt + some other random data) crc32 hoặc md5 cũng sẽ làm việc bên trong của sha1 và lưu nó trong cơ sở dữ liệu và sau đó isValid() kiểm tra db nếu khóa tồn tại?

+0

Đó là suy nghĩ đầu tiên của tôi :). – xpepermint

+0

Đừng quên rằng bạn không thể chỉ cần kiểm tra SHA1 (hoặc bất kỳ băm khác) và kiểm tra xem nó có "hợp lệ" hay không, trừ khi bạn cung cấp tất cả các dữ liệu khác ... –

+0

bạn không thể tìm thấy địa chỉ mac của đích máy tính nếu không có trên mạng nội bộ của bạn. đừng quên! – dusoft

60

Có nhiều cách để tạo khóa API. Tôi đã sử dụng 3 phương pháp sau tùy thuộc vào ứng dụng,

  1. Base62 (ngẫu nhiên). Tạo một số ngẫu nhiên an toàn lớn và Base-62 mã hóa nó. Khóa trông giống như "w5vt2bjzf8ryp63t". Điều này là tốt cho hệ thống tự cung cấp. Bạn không phải lo lắng về va chạm và các phím không phù hợp. Bạn phải kiểm tra cơ sở dữ liệu để biết liệu khóa có hợp lệ hay không.

  2. Base62 (MD5-HMAC (khóa, Bình thường hóa (giới thiệu))). Điều này hoạt động tốt nếu API chỉ được phép từ một trang web. Chỉ cần kiểm tra HMAC của người giới thiệu chuẩn hóa và bạn biết liệu khóa đó có hợp lệ hay không, không có quyền truy cập cơ sở dữ liệu. Bạn cần giữ bí mật khóa HMAC để thực hiện việc này.

  3. Tên thân thiện được gán cho con người như "example.com". Điều này làm việc tuyệt vời nếu người dùng API được yêu cầu sở hữu miền hoặc họ là đối tác của công ty bạn.

Hãy nhớ rằng không có bảo mật trong khóa API. Nó chỉ là một tên được gán cho ứng dụng API của bạn. Ngày càng có nhiều người sử dụng các cụm từ như "ID ứng dụng" hoặc "ID nhà phát triển" để phản ánh những gì thực sự là. Bạn phải gán một khóa bí mật khác nếu bạn muốn bảo mật giao thức của mình, như consumer_key/consumer_secret trong OAuth.

+3

Sự tò mò: Tại sao cụ thể là base62? Tại sao không base64 chẳng hạn? –

+22

Cơ sở 62 hạn chế bộ ký tự kết quả thành (A-Za-z0-9). (26 + 26 + 10 = 62) Điều này có nghĩa là bạn có thể đưa ra các giả định thuận tiện nhất định trong ứng dụng của bạn về cách trang điểm các phím. Chúng cũng xuất hiện phù hợp hơn (vì chúng chỉ là chữ và số) so với Base64. – rinogo

2

Cũng như đã được đề cập, tất cả đều phụ thuộc vào tình huống. Một phương pháp mà tôi cần sử dụng là xác thực url giới thiệu bằng khóa API được chỉ định cụ thể. Vì vậy, với khóa API tất cả những gì thực sự cần thiết là (giả) key = md5(referer url + name + salt) mà sau đó bạn có thể có tổng kiểm tra. Tôi biết nó đã được đề cập tương tự như trước đây, nhưng nó chỉ là theo cách đó. Đối với hàm isValid(), tất cả những gì bạn cần làm là so sánh nó với checksum và URL.

Chỉnh sửa: Chỉ cần nhận ra tuổi của câu hỏi ban đầu: S

2

Tùy thuộc vào những gì bạn muốn, bạn cũng có thể sử dụng giống như 3scale để tạo ra các phím và quản lý truy cập vào các API. Nó tạo ra các khóa, nhưng cũng theo dõi các giới hạn tốc độ, phân tích vv và cho phép các dev trên API tạo các khóa mới.

Có một thư viện PHP là một trong những kết nối: https://support.3scale.net/reference/libraries

0

Xem uniqid:

string uniqid ([ string $prefix = "" [, bool $more_entropy = false ]]) 
+3

đoán đoạn này sẽ tắt mọi người: 'Cảnh báo: Chức năng này không tạo ra các chuỗi ngẫu nhiên hoặc không thể đoán trước được. Chức năng này không được sử dụng cho mục đích bảo mật.' Nếu không: Rất vui khi biết nó ở đó. – Philzen

+2

@Philzen: Có thể. ['password_hash'] (http://php.net/manual/en/function.password-hash.php) có thể là một giải pháp thay thế thú vị. –

1

Đây là một câu hỏi cũ, nhưng tôi vấp về cùng một vấn đề ngày hôm qua, và thấy lớp này đó là RFC4122 compliant:

/*- 
* Copyright (c) 2008 Fredrik Lindberg - http://www.shapeshifter.se 
* All rights reserved. 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions 
* are met: 
* 1. Redistributions of source code must retain the above copyright 
* notice, this list of conditions and the following disclaimer. 
* 2. Redistributions in binary form must reproduce the above copyright 
* notice, this list of conditions and the following disclaimer in the 
* documentation and/or other materials provided with the distribution. 
* 
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
* 
*/ 

/* 
* UUID (RFC4122) Generator 
* http://tools.ietf.org/html/rfc4122 
* 
* Implements version 1, 3, 4 and 5 
*/ 
class GEN_UUID { 
    /* UUID versions */ 
    const UUID_TIME  = 1; /* Time based UUID */ 
    const UUID_NAME_MD5  = 3; /* Name based (MD5) UUID */ 
    const UUID_RANDOM  = 4; /* Random UUID */ 
    const UUID_NAME_SHA1  = 5; /* Name based (SHA1) UUID */ 

    /* UUID formats */ 
    const FMT_FIELD  = 100; 
    const FMT_STRING  = 101; 
    const FMT_BINARY  = 102; 
    const FMT_QWORD  = 1; /* Quad-word, 128-bit (not impl.) */ 
    const FMT_DWORD  = 2; /* Double-word, 64-bit (not impl.) */ 
    const FMT_WORD   = 4; /* Word, 32-bit (not impl.) */ 
    const FMT_SHORT  = 8; /* Short (not impl.) */ 
    const FMT_BYTE  = 16; /* Byte */ 
    const FMT_DEFAULT  = 16; 


    public function __construct() 
    { 
    } 


    /* Field UUID representation */ 
    static private $m_uuid_field = array(
     'time_low' => 0,  /* 32-bit */ 
     'time_mid' => 0,  /* 16-bit */ 
     'time_hi' => 0,   /* 16-bit */ 
     'clock_seq_hi' => 0,  /* 8-bit */ 
     'clock_seq_low' => 0,  /* 8-bit */ 
     'node' => array()  /* 48-bit */ 
    ); 

    static private $m_generate = array(
     self::UUID_TIME => "generateTime", 
     self::UUID_RANDOM => "generateRandom", 
     self::UUID_NAME_MD5 => "generateNameMD5", 
     self::UUID_NAME_SHA1 => "generateNameSHA1" 
    ); 

    static private $m_convert = array(
     self::FMT_FIELD => array(
      self::FMT_BYTE => "conv_field2byte", 
      self::FMT_STRING => "conv_field2string", 
      self::FMT_BINARY => "conv_field2binary" 
     ), 
     self::FMT_BYTE => array(
      self::FMT_FIELD => "conv_byte2field", 
      self::FMT_STRING => "conv_byte2string", 
      self::FMT_BINARY => "conv_byte2binary" 
     ), 
     self::FMT_STRING => array(
      self::FMT_BYTE => "conv_string2byte", 
      self::FMT_FIELD => "conv_string2field", 
      self::FMT_BINARY => "conv_string2binary" 
     ), 
    ); 

    /* Swap byte order of a 32-bit number */ 
    static private function swap32($x) { 
     return (($x & 0x000000ff) << 24) | (($x & 0x0000ff00) << 8) | 
      (($x & 0x00ff0000) >> 8) | (($x & 0xff000000) >> 24); 
    } 

    /* Swap byte order of a 16-bit number */ 
    static private function swap16($x) { 
     return (($x & 0x00ff) << 8) | (($x & 0xff00) >> 8); 
    } 

    /* Auto-detect UUID format */ 
    static private function detectFormat($src) { 
     if (is_string($src)) 
      return self::FMT_STRING; 
     else if (is_array($src)) { 
      $len = count($src); 
      if ($len == 1 || ($len % 2) == 0) 
       return $len; 
      else 
       return (-1); 
     } 
     else 
      return self::FMT_BINARY; 
    } 

    /* 
    * Public API, generate a UUID of 'type' in format 'fmt' for 
    * the given namespace 'ns' and node 'node' 
    */ 
    static public function generate($type=self::UUID_RANDOM, $fmt = self::FMT_STRING, $node = "", $ns = "") { 
     $func = self::$m_generate[$type]; 
     if (!isset($func)) 
      return null; 
     $conv = self::$m_convert[self::FMT_FIELD][$fmt]; 

     $uuid = self::$func($ns, $node); 
     return self::$conv($uuid); 
    } 

    /* 
    * Public API, convert a UUID from one format to another 
    */ 
    static public function convert($uuid, $from, $to) { 
     $conv = self::$m_convert[$from][$to]; 
     if (!isset($conv)) 
      return ($uuid); 

     return (self::$conv($uuid)); 
    } 

    /* 
    * Generate an UUID version 4 (pseudo random) 
    */ 
    static private function generateRandom($ns, $node) { 
     $uuid = self::$m_uuid_field; 

     $uuid['time_hi'] = (4 << 12) | (mt_rand(0, 0x1000)); 
     $uuid['clock_seq_hi'] = (1 << 7) | mt_rand(0, 128); 
     $uuid['time_low'] = mt_rand(0, 0xffff) + (mt_rand(0, 0xffff) << 16); 
     $uuid['time_mid'] = mt_rand(0, 0xffff); 
     $uuid['clock_seq_low'] = mt_rand(0, 255); 
     for ($i = 0; $i < 6; $i++) 
      $uuid['node'][$i] = mt_rand(0, 255); 
     return ($uuid); 
    } 

    /* 
    * Generate UUID version 3 and 5 (name based) 
    */ 
    static private function generateName($ns, $node, $hash, $version) { 
     $ns_fmt = self::detectFormat($ns); 
     $field = self::convert($ns, $ns_fmt, self::FMT_FIELD); 

     /* Swap byte order to keep it in big endian on all platforms */ 
     $field['time_low'] = self::swap32($field['time_low']); 
     $field['time_mid'] = self::swap16($field['time_mid']); 
     $field['time_hi'] = self::swap16($field['time_hi']); 

     /* Convert the namespace to binary and concatenate node */ 
     $raw = self::convert($field, self::FMT_FIELD, self::FMT_BINARY); 
     $raw .= $node; 

     /* Hash the namespace and node and convert to a byte array */ 
     $val = $hash($raw, true);  
     $tmp = unpack('C16', $val); 
     foreach (array_keys($tmp) as $key) 
      $byte[$key - 1] = $tmp[$key]; 

     /* Convert byte array to a field array */ 
     $field = self::conv_byte2field($byte); 

     $field['time_low'] = self::swap32($field['time_low']); 
     $field['time_mid'] = self::swap16($field['time_mid']); 
     $field['time_hi'] = self::swap16($field['time_hi']); 

     /* Apply version and constants */ 
     $field['clock_seq_hi'] &= 0x3f; 
     $field['clock_seq_hi'] |= (1 << 7); 
     $field['time_hi'] &= 0x0fff; 
     $field['time_hi'] |= ($version << 12); 

     return ($field);  
    } 
    static private function generateNameMD5($ns, $node) { 
     return self::generateName($ns, $node, "md5", 
      self::UUID_NAME_MD5); 
    } 
    static private function generateNameSHA1($ns, $node) { 
     return self::generateName($ns, $node, "sha1", 
      self::UUID_NAME_SHA1); 
    } 

    /* 
    * Generate UUID version 1 (time based) 
    */ 
    static private function generateTime($ns, $node) { 
     $uuid = self::$m_uuid_field; 

     /* 
     * Get current time in 100 ns intervals. The magic value 
     * is the offset between UNIX epoch and the UUID UTC 
     * time base October 15, 1582. 
     */ 
     $tp = gettimeofday(); 
     $time = ($tp['sec'] * 10000000) + ($tp['usec'] * 10) + 
      0x01B21DD213814000; 

     $uuid['time_low'] = $time & 0xffffffff; 
     /* Work around PHP 32-bit bit-operation limits */ 
     $high = intval($time/0xffffffff); 
     $uuid['time_mid'] = $high & 0xffff; 
     $uuid['time_hi'] = (($high >> 16) & 0xfff) | (self::UUID_TIME << 12); 

     /* 
     * We don't support saved state information and generate 
     * a random clock sequence each time. 
     */ 
     $uuid['clock_seq_hi'] = 0x80 | mt_rand(0, 64); 
     $uuid['clock_seq_low'] = mt_rand(0, 255); 

     /* 
     * Node should be set to the 48-bit IEEE node identifier, but 
     * we leave it for the user to supply the node. 
     */ 
     for ($i = 0; $i < 6; $i++) 
      $uuid['node'][$i] = ord(substr($node, $i, 1)); 

     return ($uuid); 
    } 

    /* Assumes correct byte order */ 
    static private function conv_field2byte($src) { 
     $uuid[0] = ($src['time_low'] & 0xff000000) >> 24; 
     $uuid[1] = ($src['time_low'] & 0x00ff0000) >> 16; 
     $uuid[2] = ($src['time_low'] & 0x0000ff00) >> 8; 
     $uuid[3] = ($src['time_low'] & 0x000000ff); 
     $uuid[4] = ($src['time_mid'] & 0xff00) >> 8; 
     $uuid[5] = ($src['time_mid'] & 0x00ff); 
     $uuid[6] = ($src['time_hi'] & 0xff00) >> 8; 
     $uuid[7] = ($src['time_hi'] & 0x00ff); 
     $uuid[8] = $src['clock_seq_hi']; 
     $uuid[9] = $src['clock_seq_low']; 

     for ($i = 0; $i < 6; $i++) 
      $uuid[10+$i] = $src['node'][$i]; 

     return ($uuid); 
    } 

    static private function conv_field2string($src) { 
     $str = sprintf(
      '%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x', 
      ($src['time_low']), ($src['time_mid']), ($src['time_hi']), 
      $src['clock_seq_hi'], $src['clock_seq_low'], 
      $src['node'][0], $src['node'][1], $src['node'][2], 
      $src['node'][3], $src['node'][4], $src['node'][5]); 
     return ($str); 
    } 

    static private function conv_field2binary($src) { 
     $byte = self::conv_field2byte($src); 
     return self::conv_byte2binary($byte); 
    } 

    static private function conv_byte2field($uuid) { 
     $field = self::$m_uuid_field; 
     $field['time_low'] = ($uuid[0] << 24) | ($uuid[1] << 16) | 
      ($uuid[2] << 8) | $uuid[3]; 
     $field['time_mid'] = ($uuid[4] << 8) | $uuid[5]; 
     $field['time_hi'] = ($uuid[6] << 8) | $uuid[7]; 
     $field['clock_seq_hi'] = $uuid[8]; 
     $field['clock_seq_low'] = $uuid[9]; 

     for ($i = 0; $i < 6; $i++) 
      $field['node'][$i] = $uuid[10+$i]; 
     return ($field); 
    } 

    static public function conv_byte2string($src) { 
     $field = self::conv_byte2field($src); 
     return self::conv_field2string($field); 
    } 

    static private function conv_byte2binary($src) { 
     $raw = pack('C16', $src[0], $src[1], $src[2], $src[3], 
      $src[4], $src[5], $src[6], $src[7], $src[8], $src[9], 
      $src[10], $src[11], $src[12], $src[13], $src[14], $src[15]); 
     return ($raw); 
    } 

    static private function conv_string2field($src) { 
     $parts = sscanf($src, '%x-%x-%x-%x-%02x%02x%02x%02x%02x%02x'); 
     $field = self::$m_uuid_field; 
     $field['time_low'] = ($parts[0]); 
     $field['time_mid'] = ($parts[1]); 
     $field['time_hi'] = ($parts[2]); 
     $field['clock_seq_hi'] = ($parts[3] & 0xff00) >> 8; 
     $field['clock_seq_low'] = $parts[3] & 0x00ff; 
     for ($i = 0; $i < 6; $i++) 
      $field['node'][$i] = $parts[4+$i]; 

     return ($field); 
    } 

    static private function conv_string2byte($src) { 
     $field = self::conv_string2field($src); 
     return self::conv_field2byte($field); 
    } 

    static private function conv_string2binary($src) { 
     $byte = self::conv_string2byte($src); 
     return self::conv_byte2binary($byte); 
    } 
} 

Hy vọng rằng sẽ giúp

0

Bạn chỉ có thể sử dụng md5(uniqid()) và chia thành các phần hoặc định dạng theo cách thích hợp khác.

5

Dưới đây là câu trả lời đơn giản của tôi cho câu hỏi này:

$key = implode('-', str_split(substr(strtolower(md5(microtime().rand(1000, 9999))), 0, 30), 6)); 
0

GUID sẽ làm việc nhưng không mã hóa an toàn.

Câu trả lời của máy chủ sử dụng phương pháp băm md5 hoặc sha1 trên microtime() hoặc mt_rand.

Việc băm nhỏ một dấu trang, uuid hoặc dấu thời gian sẽ không nhất thiết tạo ra kết quả duy nhất! Thực tế băm làm tăng cơ hội va chạm vì vậy tôi sẽ mạnh mẽ khuyên bạn nên chống lại điều này.