2

我已经设置了 nginx 用户 ID 模块,以便在对服务器的请求中生成 uid cookie 以进行匿名跟踪,虽然设置 cookie 的一切都按预期进行,但我无法弄清楚应该如何解析这些 cookie(在 Python 中)以进行进一步分析。

根据 nginx 的文档(http://nginx.org/en/docs/http/ngx_http_userid_module.html#userid_service),http_userid_module 完全符合 apache 的 mod_uid 并根据 apache 的 mod_uid 文档(http://www.lexa.ru/ programs/mod-uid-eng.html ) cookie 值实际上包含有价值的数据,例如发出 cookie 的时间戳。

base64 解码部分很简单 :) 想知道这里是否有人可以帮助完成解析这些 cookie 中的数据所需的其余操作?

4

2 回答 2

5
import base64
import socket
import struct


def decode_cookie(cookie):
    """decode a u cookie into an uid

    :param cookie: a cookie value that will be decoded into a uid
    :return: string representing the uid

    This algorithm is for version 2 of http://wiki.nginx.org/HttpUseridModule.

    This nginx module follows the apache mod_uid module algorithm, which is
    documented here: http://www.lexa.ru/programs/mod-uid-eng.html.

    """
    # get the raw binary value
    binary_cookie = base64.b64decode(cookie)

    # unpack into 4 parts, each a network byte orderd 32 bit unsigned int
    unsigned_ints = struct.unpack('!4I', binary_cookie)

    # convert from network (big-endian) to host byte (probably little-endian) order
    host_byte_order_ints = [socket.ntohl(i) for i in unsigned_ints]

    # convert to upper case hex value
    uid = 'u=' + ''.join(['{0:08X}'.format(h) for h in host_byte_order_ints])

    return uid


def encode_uid(uid):
    """encode an uid into a u cookie

    :param uid: an uid that will be encoded into a cookie.
    :return: string representing the u cookie

    The algorithm is for version 2 of http://wiki.nginx.org/HttpUseridModule.

    This nginx module follows the apache mod_uid module algorithm, which is
    documented here: http://www.lexa.ru/programs/mod-uid-eng.html.

    """
    # get the hex value of the uid
    hex_value = uid.split('=')[1]

    # convert 128 bit string into 4 32 bit integers
    host_byte_order_ints = [int(hex_value[i:i+8], 16) for i in range(0, 32, 8)]

    # convert from host byte (probably little-endian) to network byte (big-endian) order
    unsigned_ints = [socket.htonl(i) for i in host_byte_order_ints]

    # convert to raw binary value
    binary_cookie = struct.pack('!4I', *unsigned_ints)

    # get the base64 version of the cookie
    cookie = base64.b64encode(binary_cookie)

    return cookie
于 2013-09-26T20:02:35.407 回答
0

@d3w4rd 在 PHP 中的答案的反向移植,以防有人正在寻找它。

class NginxUniqid
{
    public static function decodeCookie($cookie)
    {
        return strtoupper(join('', array_map(function ($e) {
            return str_pad(
                base_convert($e, 10, 16),
                8, '0', STR_PAD_LEFT
            );
        }, unpack('I4', base64_decode($cookie)))));
    }

    public static function encodeUid($hex)
    {
        return base64_encode(pack(
            'I4',
            base_convert(substr($hex, 0, 8), 16, 10),
            base_convert(substr($hex, 8, 8), 16, 10),
            base_convert(substr($hex, 16, 8), 16, 10),
            base_convert(substr($hex, 24, 8), 16, 10)
        ));
    }
}
于 2018-01-22T15:17:32.903 回答