将qq空间的说说同步至博客园系列之通过Cookie和qq空间g_tk参数取得空间数据(2)...

大家可以先看下这篇文章,将微博或者qq空间的说说同步至博客园 wcf+js(ajax)跨域请求(1),在该文里面,对使用javascript调用wcf到我本机取数据作了介绍。不过吐槽一下,该文发布没多久,就被博客园移除首页了,博主可是花了五个小时调试代码,部署环境。最后太晚了,所以文章写得仓促了点。文章写得不咋滴。大概是博客园管理认为我没写完,所以移除了首页。博主可真是冤枉。最后这一系列文章写完,博主会重新详细写一下如何通过javascript调用wcf。废话不多说。我们今天来看一下,如何在本地去qq空间的数据。

刚开始博主的思路是写一个Chrome扩展,然后每次当我打开空间的时候自动记录数据到本地。后来感觉javascript操作数据很不方便,便决定还是使用C#来取数据。

另外先透漏一下,从qq空间取数据到博客园后博主的思路。博主打算使用Knockout组件的形式在博客园渲染页面。所以现在把qq空间同步至博客园这个工程大概有以下三步。一是本地服务端取数据存储到数据库。二是通过javascript调用wcf将数据传输到博客园,最后是使用KnockOut将数据渲染至页面。

另:博主本打算模拟qq空间登录的方式来取数据。不过qq空间登录的模块是使用插件的形式登录的。了解其机制代价太大。所以决定通过下面这种方式取数据。

另:现在页面上还看不到效果。最后一步使用KnockOut将数据渲染至页面博主还没开始准备。现在我们开始到qq空间取数据。

确定qq空间异步无刷新填充数据的报文必要参数

我们仔细观察下qq空间首页,会发现qq空间全部动态那儿有个刷新的按钮

点击此处会异步去qq服务器取数据。如下图

我们将该链接访问以下。

http://user.qzone.qq.com/p/ic2.s51/cgi-bin/feeds/feeds3_html_more?uin=11******88&scope=0&view=1&daylist=&uinlist=&gid=&flag=1&filter=all&applist=all&refresh=0&aisortEndTime=0&aisortOffset=0&getAisort=0&aisortBeginTime=0&pagenum=2&externparam=basetime%3D1428817036%26pagenum%3D2%26dayvalue%3D0&firstGetGroup=0&icServerTime=0&mixnocache=0&scene=0&begintime=1428817036&count=10&dayspac=0&sidomain=cm.qzonestyle.gtimg.cn&useutf8=1&outputhtmlfeed=1&rd=0.1990418911445886&g_tk=1385204724

如上所示,可以通过这样取到我们需要的json数据。

那么问题来了。我们如果要使用System.Net该类库提供的服务来模拟http请求报文,都需要什么条件么。毫无疑问,在这儿需要的是,一个是get请求的url,包括该get请求传递过去的参数。以及报文发送时随报文发送的cookie.

需求已经明了。我们需要得到get参数,以及发送的cookie.

破解g_tk=1385204724参数的秘密

观察上面我发布get链接。首先最想说的是,这参数也太**多了。不过没问题。我们多对比几次就会发现,上面的大部分参数都是不怎么变化的。其中一个begintime参数,博主试了下并没有多大的影响。几经确认,发现该get请求最重要的参数只有一个,那就是g_tk参数。该参数和cookie几乎决定了我们请求数据的成败。那么该参数到底是在哪儿来的呢。

要想知道该参数怎么来的,我们就要知道当我们点击刷新的时候,javascript函数到底做了什么。怎样生成的ajax请求呢。那么我们就需要知道当我们点击该刷新按钮的时候执行的是什么函数,也就是该按钮到底和哪个javascript函数绑定。那么问题来了----如何找到dom元素绑定的函数呢。我们首先在chrome浏览器下f12调试。

如下图

 

博主在这儿找了半天,也没找到有用的信息,不过幸好博主找到了一个神器

该插件可以提供让我们看dom元素绑定函数的功能,虽说有些限制,不过在这儿确实发挥了作用。

既然找到了该函数调用的函数,那么顺藤摸瓜。博主找到了下面这个函数。

  pingCgi: function () {
            var a =
            "http://" + g_R_Domain + "/cgi-bin/user/qzone_cgi_msg_getcnt2"; setInterval(function () { QZFL.pingSender(a + "?uin=" + g_iLoginUin + "&bm=" + g_LoginBitmap + "&v=" + c.getCGISeed("_QZN_TodoMsgCnt") + "&g_tk=" + QZONE.FrontPage.getACSRFToken() + "&g=" + Math.random(), 0) }, 6E5)
}

显然g_tk是通过QZONE.FrontPage.getACSRFToken()这个函数生成的。我们继续找到该函数。

QZONE.FrontPage.getACSRFToken = function (a) {
    a = QZFL.util.URI(a);
    var b;
    a && (a.host && 0 < a.host.indexOf("qzone.qq.com") ? b = QZFL.cookie.get("p_skey") : a.host && 0 < a.host.indexOf("qq.com") && (b = QZFL.cookie.get("skey")));
    b || (b = QZFL.cookie.get("skey") || QZFL.cookie.get("rv2"));
    a = 5381;
    for (var c = 0, d = b.length; c < d; ++c)
        a += (a << 5) + b.charAt(c).charCodeAt();
    return a & 2147483647
};

找到了个函数那么问题就清楚了。该函数调用了cookie里面的P_skey参数来生成了该g_tk. 我们可以使用C#来重写该javascript函数。

  public string getg_tk(string str)
  {
      var b = str;
      var a = 5381;
      for (int c = 0, d = b.Length; c < d; ++c)
//这儿是javascript代码的c#实现。b[c]取到字符串在c索引处的字符。强转为int既是将char转为Unicode a += (a << 5) + (int)b[c]; return (a & 2147483647).ToString(); }

之后我们传入cookie里面的p_skey=rK6xJHZPMWUxBj6ehdS5CoILGC8aMt7EPEgNYVRBbRU_;会发现生成的g_tk和我们用来调用的g_tk=1385204724相等。如下图。

 

现在解决了get参数的问题,我们再来解决我们的cookie问题。

使用sqllite数据库获取chrome cookie数据表

我们找到chrome cookie所在的文件夹。

使用notepad打开,会发现是乱码。这是因为chrome后来版本的cookie都是通过加密后存储到了sqlite数据库里面。

为我们的项目添加如下引用。同时在我们项目的bin问价夹下添加SQLite.Interop.dll类库。

我们添加一个sqllitehelper帮助类。

//添加一个静态帮助类 
public static class SqlLiteHelper { public static DataTable ExecuteSql(System.Data.IDbConnection connection, string sql) { var cmd = connection.CreateCommand(); cmd.CommandText = sql; using (var reader = cmd.ExecuteReader()) { var dataTable = new DataTable(); dataTable.Load(reader); return dataTable; } } }
//这是sqllite数据库的连接字符串  
string connectionString = @"Data Source=C:\Documents and Settings\wfm\Local Settings\Application Data\Google\Chrome\User Data\Default\Cookies";
//使用using用来释放非托管资源,垃圾回收。 using (var conn = new System.Data.SQLite.SQLiteConnection(connectionString)) { conn.Open(); DataTable db = SqlLiteHelper.ExecuteSql(conn, "select host_key,name,value,encrypted_value from cookies;"); }

使用上面的代码我们就可取到sqllite数据库的数据。

 

使用crypt32.dll下的CryptUnprotectData函数解密chrome cookie

如上图取到cookie的数据后我们会发现取到的value值是空的,同时有一个encrypted_value的byte数组.随便google一下我们就知道这是chrome新版本里面存储的cookie数据。不过被chrome加密了。那么现在我们就需要解密cookie.如何解密,博主其实一点也不会。不过幸好有大神会。搜索相关资源,我们知道需要用到

crypt32.dll下的CryptUnprotectData函数来解密。我们寻找资源会发现相关的资料都是使用Python实现的。并没有c#下面的代码可以拿来直接用。相关连接如下

Chrome 33+浏览器 Cookies encrypted_value解密脚本(python实现),还有一些其它类似的资料。这里就不列出了。

我们新建一个类DPAPI相关代码如下。

///
// SAMPLE: Encryption and decryption using DPAPI functions.
//
// To run this sample, create a new Visual C# project using the Console
// Application template and replace the contents of the Class1.cs file
// with the code below.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (C) 2003 Obviex(TM). All rights reserved.
//
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

/// <summary>
/// Encrypts and decrypts data using DPAPI functions.
/// </summary>
public class DPAPI
{
    // Wrapper for DPAPI CryptProtectData function.
    [DllImport("crypt32.dll",
                SetLastError = true,
                CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern
        bool CryptProtectData(ref DATA_BLOB pPlainText,
                                    string szDescription,
                                ref DATA_BLOB pEntropy,
                                    IntPtr pReserved,
                                ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,
                                    int dwFlags,
                                ref DATA_BLOB pCipherText);

    // Wrapper for DPAPI CryptUnprotectData function.
    [DllImport("crypt32.dll",
                SetLastError = true,
                CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern
        bool CryptUnprotectData(ref DATA_BLOB pCipherText,
                                ref string pszDescription,
                                ref DATA_BLOB pEntropy,
                                    IntPtr pReserved,
                                ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,
                                    int dwFlags,
                                ref DATA_BLOB pPlainText);

    // BLOB structure used to pass data to DPAPI functions.
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct DATA_BLOB
    {
        public int cbData;
        public IntPtr pbData;
    }

    // Prompt structure to be used for required parameters.
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct CRYPTPROTECT_PROMPTSTRUCT
    {
        public int cbSize;
        public int dwPromptFlags;
        public IntPtr hwndApp;
        public string szPrompt;
    }

    // Wrapper for the NULL handle or pointer.
    static private IntPtr NullPtr = ((IntPtr)((int)(0)));

    // DPAPI key initialization flags.
    private const int CRYPTPROTECT_UI_FORBIDDEN = 0x1;
    private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;

    /// <summary>
    /// Initializes empty prompt structure.
    /// </summary>
    /// <param name="ps">
    /// Prompt parameter (which we do not actually need).
    /// </param>
    private static void InitPrompt(ref CRYPTPROTECT_PROMPTSTRUCT ps)
    {
        ps.cbSize = Marshal.SizeOf(
                                  typeof(CRYPTPROTECT_PROMPTSTRUCT));
        ps.dwPromptFlags = 0;
        ps.hwndApp = NullPtr;
        ps.szPrompt = null;
    }

    /// <summary>
    /// Initializes a BLOB structure from a byte array.
    /// </summary>
    /// <param name="data">
    /// Original data in a byte array format.
    /// </param>
    /// <param name="blob">
    /// Returned blob structure.
    /// </param>
    private static void InitBLOB(byte[] data, ref DATA_BLOB blob)
    {
        // Use empty array for null parameter.
        if (data == null)
            data = new byte[0];

        // Allocate memory for the BLOB data.
        blob.pbData = Marshal.AllocHGlobal(data.Length);

        // Make sure that memory allocation was successful.
        if (blob.pbData == IntPtr.Zero)
            throw new Exception(
                "Unable to allocate data buffer for BLOB structure.");

        // Specify number of bytes in the BLOB.
        blob.cbData = data.Length;

        // Copy data from original source to the BLOB structure.
        Marshal.Copy(data, 0, blob.pbData, data.Length);
    }

    // Flag indicating the type of key. DPAPI terminology refers to
    // key types as user store or machine store.
    public enum KeyType { UserKey = 1, MachineKey };

    // It is reasonable to set default key type to user key.
    private static KeyType defaultKeyType = KeyType.UserKey;

    /// <summary>
    /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    /// string value with a user-specific key. This function does not
    /// specify data description and additional entropy.
    /// </summary>
    /// <param name="plainText">
    /// Plaintext data to be encrypted.
    /// </param>
    /// <returns>
    /// Encrypted value in a base64-encoded format.
    /// </returns>
    public static string Encrypt(string plainText)
    {
        return Encrypt(defaultKeyType, plainText, String.Empty,
                        String.Empty);
    }

    /// <summary>
    /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    /// string value. This function does not specify data description
    /// and additional entropy.
    /// </summary>
    /// <param name="keyType">
    /// Defines type of encryption key to use. When user key is
    /// specified, any application running under the same user account
    /// as the one making this call, will be able to decrypt data.
    /// Machine key will allow any application running on the same
    /// computer where data were encrypted to perform decryption.
    /// Note: If optional entropy is specifed, it will be required
    /// for decryption.
    /// </param>
    /// <param name="plainText">
    /// Plaintext data to be encrypted.
    /// </param>
    /// <returns>
    /// Encrypted value in a base64-encoded format.
    /// </returns>
    public static string Encrypt(KeyType keyType, string plainText)
    {
        return Encrypt(keyType, plainText, String.Empty,
                        String.Empty);
    }

    /// <summary>
    /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    /// string value. This function does not specify data description.
    /// </summary>
    /// <param name="keyType">
    /// Defines type of encryption key to use. When user key is
    /// specified, any application running under the same user account
    /// as the one making this call, will be able to decrypt data.
    /// Machine key will allow any application running on the same
    /// computer where data were encrypted to perform decryption.
    /// Note: If optional entropy is specifed, it will be required
    /// for decryption.
    /// </param>
    /// <param name="plainText">
    /// Plaintext data to be encrypted.
    /// </param>
    /// <param name="entropy">
    /// Optional entropy which - if specified - will be required to
    /// perform decryption.
    /// </param>
    /// <returns>
    /// Encrypted value in a base64-encoded format.
    /// </returns>
    public static string Encrypt(KeyType keyType,
                                 string plainText,
                                 string entropy)
    {
        return Encrypt(keyType, plainText, entropy, String.Empty);
    }

    /// <summary>
    /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    /// string value.
    /// </summary>
    /// <param name="keyType">
    /// Defines type of encryption key to use. When user key is
    /// specified, any application running under the same user account
    /// as the one making this call, will be able to decrypt data.
    /// Machine key will allow any application running on the same
    /// computer where data were encrypted to perform decryption.
    /// Note: If optional entropy is specifed, it will be required
    /// for decryption.
    /// </param>
    /// <param name="plainText">
    /// Plaintext data to be encrypted.
    /// </param>
    /// <param name="entropy">
    /// Optional entropy which - if specified - will be required to
    /// perform decryption.
    /// </param>
    /// <param name="description">
    /// Optional description of data to be encrypted. If this value is
    /// specified, it will be stored along with encrypted data and
    /// returned as a separate value during decryption.
    /// </param>
    /// <returns>
    /// Encrypted value in a base64-encoded format.
    /// </returns>
    public static string Encrypt(KeyType keyType,
                                 string plainText,
                                 string entropy,
                                 string description)
    {
        // Make sure that parameters are valid.
        if (plainText == null) plainText = String.Empty;
        if (entropy == null) entropy = String.Empty;

        // Call encryption routine and convert returned bytes into
        // a base64-encoded value.
        return Convert.ToBase64String(
                Encrypt(keyType,
                        Encoding.UTF8.GetBytes(plainText),
                        Encoding.UTF8.GetBytes(entropy),
                        description));
    }

    /// <summary>
    /// Calls DPAPI CryptProtectData function to encrypt an array of
    /// plaintext bytes.
    /// </summary>
    /// <param name="keyType">
    /// Defines type of encryption key to use. When user key is
    /// specified, any application running under the same user account
    /// as the one making this call, will be able to decrypt data.
    /// Machine key will allow any application running on the same
    /// computer where data were encrypted to perform decryption.
    /// Note: If optional entropy is specifed, it will be required
    /// for decryption.
    /// </param>
    /// <param name="plainTextBytes">
    /// Plaintext data to be encrypted.
    /// </param>
    /// <param name="entropyBytes">
    /// Optional entropy which - if specified - will be required to
    /// perform decryption.
    /// </param>
    /// <param name="description">
    /// Optional description of data to be encrypted. If this value is
    /// specified, it will be stored along with encrypted data and
    /// returned as a separate value during decryption.
    /// </param>
    /// <returns>
    /// Encrypted value.
    /// </returns>
    public static byte[] Encrypt(KeyType keyType,
                                 byte[] plainTextBytes,
                                 byte[] entropyBytes,
                                 string description)
    {
        // Make sure that parameters are valid.
        if (plainTextBytes == null) plainTextBytes = new byte[0];
        if (entropyBytes == null) entropyBytes = new byte[0];
        if (description == null) description = String.Empty;

        // Create BLOBs to hold data.
        DATA_BLOB plainTextBlob = new DATA_BLOB();
        DATA_BLOB cipherTextBlob = new DATA_BLOB();
        DATA_BLOB entropyBlob = new DATA_BLOB();

        // We only need prompt structure because it is a required
        // parameter.
        CRYPTPROTECT_PROMPTSTRUCT prompt =
                                  new CRYPTPROTECT_PROMPTSTRUCT();
        InitPrompt(ref prompt);

        try
        {
            // Convert plaintext bytes into a BLOB structure.
            try
            {
                InitBLOB(plainTextBytes, ref plainTextBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                    "Cannot initialize plaintext BLOB.", ex);
            }

            // Convert entropy bytes into a BLOB structure.
            try
            {
                InitBLOB(entropyBytes, ref entropyBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                    "Cannot initialize entropy BLOB.", ex);
            }

            // Disable any types of UI.
            int flags = CRYPTPROTECT_UI_FORBIDDEN;

            // When using machine-specific key, set up machine flag.
            if (keyType == KeyType.MachineKey)
                flags |= CRYPTPROTECT_LOCAL_MACHINE;

            // Call DPAPI to encrypt data.
            bool success = CryptProtectData(ref plainTextBlob,
                                                description,
                                            ref entropyBlob,
                                                IntPtr.Zero,
                                            ref prompt,
                                                flags,
                                            ref cipherTextBlob);
            // Check the result.
            if (!success)
            {
                // If operation failed, retrieve last Win32 error.
                int errCode = Marshal.GetLastWin32Error();

                // Win32Exception will contain error message corresponding
                // to the Windows error code.
                throw new Exception(
                    "CryptProtectData failed.", new Win32Exception(errCode));
            }

            // Allocate memory to hold ciphertext.
            byte[] cipherTextBytes = new byte[cipherTextBlob.cbData];

            // Copy ciphertext from the BLOB to a byte array.
            Marshal.Copy(cipherTextBlob.pbData,
                            cipherTextBytes,
                            0,
                            cipherTextBlob.cbData);

            // Return the result.
            return cipherTextBytes;
        }
        catch (Exception ex)
        {
            throw new Exception("DPAPI was unable to encrypt data.", ex);
        }
        // Free all memory allocated for BLOBs.
        finally
        {
            if (plainTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(plainTextBlob.pbData);

            if (cipherTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(cipherTextBlob.pbData);

            if (entropyBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(entropyBlob.pbData);
        }
    }

    /// <summary>
    /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    /// This function does not use additional entropy and does not
    /// return data description.
    /// </summary>
    /// <param name="cipherText">
    /// Encrypted data formatted as a base64-encoded string.
    /// </param>
    /// <returns>
    /// Decrypted data returned as a UTF-8 string.
    /// </returns>
    /// <remarks>
    /// When decrypting data, it is not necessary to specify which
    /// type of encryption key to use: user-specific or
    /// machine-specific; DPAPI will figure it out by looking at
    /// the signature of encrypted data.
    /// </remarks>
    public static string Decrypt(string cipherText)
    {
        string description;

        return Decrypt(cipherText, String.Empty, out description);
    }

    /// <summary>
    /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    /// This function does not use additional entropy.
    /// </summary>
    /// <param name="cipherText">
    /// Encrypted data formatted as a base64-encoded string.
    /// </param>
    /// <param name="description">
    /// Returned description of data specified during encryption.
    /// </param>
    /// <returns>
    /// Decrypted data returned as a UTF-8 string.
    /// </returns>
    /// <remarks>
    /// When decrypting data, it is not necessary to specify which
    /// type of encryption key to use: user-specific or
    /// machine-specific; DPAPI will figure it out by looking at
    /// the signature of encrypted data.
    /// </remarks>
    public static string Decrypt(string cipherText,
                                 out string description)
    {
        return Decrypt(cipherText, String.Empty, out description);
    }

    /// <summary>
    /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    /// </summary>
    /// <param name="cipherText">
    /// Encrypted data formatted as a base64-encoded string.
    /// </param>
    /// <param name="entropy">
    /// Optional entropy, which is required if it was specified during
    /// encryption.
    /// </param>
    /// <param name="description">
    /// Returned description of data specified during encryption.
    /// </param>
    /// <returns>
    /// Decrypted data returned as a UTF-8 string.
    /// </returns>
    /// <remarks>
    /// When decrypting data, it is not necessary to specify which
    /// type of encryption key to use: user-specific or
    /// machine-specific; DPAPI will figure it out by looking at
    /// the signature of encrypted data.
    /// </remarks>
    public static string Decrypt(string cipherText,
                                     string entropy,
                                 out string description)
    {
        // Make sure that parameters are valid.
        if (entropy == null) entropy = String.Empty;

        return Encoding.UTF8.GetString(
                    Decrypt(Convert.FromBase64String(cipherText),
                                Encoding.UTF8.GetBytes(entropy),
                            out description));
    }

    /// <summary>
    /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    /// </summary>
    /// <param name="cipherTextBytes">
    /// Encrypted data.
    /// </param>
    /// <param name="entropyBytes">
    /// Optional entropy, which is required if it was specified during
    /// encryption.
    /// </param>
    /// <param name="description">
    /// Returned description of data specified during encryption.
    /// </param>
    /// <returns>
    /// Decrypted data bytes.
    /// </returns>
    /// <remarks>
    /// When decrypting data, it is not necessary to specify which
    /// type of encryption key to use: user-specific or
    /// machine-specific; DPAPI will figure it out by looking at
    /// the signature of encrypted data.
    /// </remarks>
    public static byte[] Decrypt(byte[] cipherTextBytes,
                                     byte[] entropyBytes,
                                 out string description)
    {
        // Create BLOBs to hold data.
        DATA_BLOB plainTextBlob = new DATA_BLOB();
        DATA_BLOB cipherTextBlob = new DATA_BLOB();
        DATA_BLOB entropyBlob = new DATA_BLOB();

        // We only need prompt structure because it is a required
        // parameter.
        CRYPTPROTECT_PROMPTSTRUCT prompt =
                                  new CRYPTPROTECT_PROMPTSTRUCT();
        InitPrompt(ref prompt);

        // Initialize description string.
        description = String.Empty;

        try
        {
            // Convert ciphertext bytes into a BLOB structure.
            try
            {
                InitBLOB(cipherTextBytes, ref cipherTextBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                    "Cannot initialize ciphertext BLOB.", ex);
            }

            // Convert entropy bytes into a BLOB structure.
            try
            {
                InitBLOB(entropyBytes, ref entropyBlob);
            }
            catch (Exception ex)
            {
                throw new Exception(
                    "Cannot initialize entropy BLOB.", ex);
            }

            // Disable any types of UI. CryptUnprotectData does not
            // mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of
            // supported flags so we will not set it up.
            int flags = CRYPTPROTECT_UI_FORBIDDEN;

            // Call DPAPI to decrypt data.
            bool success = CryptUnprotectData(ref cipherTextBlob,
                                              ref description,
                                              ref entropyBlob,
                                                  IntPtr.Zero,
                                              ref prompt,
                                                  flags,
                                              ref plainTextBlob);

            // Check the result.
            if (!success)
            {
                // If operation failed, retrieve last Win32 error.
                int errCode = Marshal.GetLastWin32Error();

                // Win32Exception will contain error message corresponding
                // to the Windows error code.
                throw new Exception(
                    "CryptUnprotectData failed.", new Win32Exception(errCode));
            }

            // Allocate memory to hold plaintext.
            byte[] plainTextBytes = new byte[plainTextBlob.cbData];

            // Copy ciphertext from the BLOB to a byte array.
            Marshal.Copy(plainTextBlob.pbData,
                         plainTextBytes,
                         0,
                         plainTextBlob.cbData);

            // Return the result.
            return plainTextBytes;
        }
        catch (Exception ex)
        {
            throw new Exception("DPAPI was unable to decrypt data.", ex);
        }
        // Free all memory allocated for BLOBs.
        finally
        {
            if (plainTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(plainTextBlob.pbData);

            if (cipherTextBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(cipherTextBlob.pbData);

            if (entropyBlob.pbData != IntPtr.Zero)
                Marshal.FreeHGlobal(entropyBlob.pbData);
        }
    }
}

我们可以通过如下调用解密cookie:

  Encrypted_value = DPAPI.Decrypt(Convert.ToBase64String(cookieContent))

现在关于模拟http报文请求的条件已经都准备好了。

使用System.net类库模拟http请求报文

 HttpResponseParameter responseParameter1 = httpProvider.Excute(new HttpRequestParameter
            {
                Url = "http://user.qzone.qq.com/p/ic2.s51/cgi-bin/feeds/feeds3_html_more?uin=11******88&scope=0&view=1&daylist=&uinlist=&gid=&flag=1&filter=all&applist=all&refresh=0&aisortEndTime=0&aisortOffset=0&getAisort=0&aisortBeginTime=0&pagenum=2&externparam=basetime%3D1428810895%26pagenum%3D2%26dayvalue%3D0&firstGetGroup=0&icServerTime=0&mixnocache=0&scene=0&begintime=1428810895&count=10&dayspac=0&sidomain=cm.qzonestyle.gtimg.cn&useutf8=1&outputhtmlfeed=1&rd=0.9383603150490671&g_tk=" + getg_tk(GetCookieStr("p_skey").Split('=')[1].Replace(";", "")),
                IsPost = false,
                Encoding = Encoding.UTF8,
                Cookie = new HttpCookieType() { CookieCollection = addCookieToContainer(cookieSend) }
            });

注意上面我使用了一个类库,也是园子里的一位大神写的,大家可以自己去下载。

.Net(c#)模拟Http请求之HttpWebRequest封装

  

现在,所有的难点我们都一一解决了。现在我们运行代码

OK,我们需要的数据都取到了。但是注意一个问题,取数据的时候只有我们登陆qq空间也就是qq空间的cookie有效的时候才可以取到数据。

 现在我们可以将数据存储到数据。等待javascript调用wcf来读取数据

本文地址:http://www.cnblogs.com/santian/p/4420877.html

博客地址:http://www.cnblogs.com/santian/

转载请以超链接形式标明文章原始出处。

转载于:https://www.cnblogs.com/santian/p/4420877.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 美国西储大学对轴承数据进行解读的研究是一个关于轴承寿命预测的重要工作。在这项研究中,他们收集了大量的轴承运行数据,并进行了详细的分析和解读。 研究表明,轴承的寿命可被分为三个阶段:初期阶段、中期阶段和末期阶段。其中,初期阶段是指轴承在运行初期的阶段,此时轴承寿命可能在较短的时间内会出现故障。而中期阶段是指轴承在运行中期的阶段,此时轴承的故障概率开始逐渐增加。最后,末期阶段是指轴承在运行末期的阶段,此时轴承的寿命即将到达结束。 此外,研究还发现轴承的寿命与一些关键参数有关。其中,轴承的转速是影响寿命的重要因素之一,较高的转速会加速轴承的磨损和疲劳,从而缩短其寿命。此外,轴承的负载也会对其寿命产生影响,较大的负载也会使轴承更容易发生故障。同时,轴承的润滑情况也是一个关键因素,良好的润滑可以减少摩擦和磨损,延长轴承的寿命。 综上所述,美国西储大学对轴承数据进行的解读研究为我们深入了解轴承的运行特性和寿命预测提供了重要依据。通过对轴承运行数据的分析,我们可以更好地了解轴承的工作状态,为轴承的维护和替换提供科学依据,从而提高设备的可靠性和使用寿命。 ### 回答2: 美国西储大学轴承数据解读是指利用西储大学提供的轴承数据,对该数据进行分析和解读的过程。轴承是一种用于支持旋转机械部件的重要元件,它在各种工业领域中都有广泛的应用。通过对轴承数据的解读,可以了解轴承的工作性能、故障原因以及预测轴承的寿命等重要信息。 在解读轴承数据时,可以从多个角度进行分析。首先,可以从轴承的振动信号入手,通过分析轴承的振动频谱、特征值等信息,判断轴承是否存在故障,并确定故障的类型和程度。同时,还可以通过分析轴承的温度变化,推断轴承的摩擦状况和润滑效果,从而评估轴承的工作状态。 其次,可以通过统计学方法对轴承数据进行分析,例如计算轴承寿命的可靠度和概率分布,预测轴承的使用寿命。此外,还可以通过对不同轴承之间的性能指标进行比较,评估不同轴承的质量和性能差异。 最后,还可以将轴承数据与其他相关数据进行关联分析,例如将轴承数据与工作环境数据、润滑剂使用情况等进行对比,找出对轴承寿命和工作性能影响较大的因素。 综上所述,美国西储大学轴承数据解读是通过对提供的轴承数据进行振动分析、统计学分析和关联分析,获得轴承工作状态、预测寿命以及评估性能等方面的信息的过程。这些解读结果可以为轴承的维护保养和优化设计提供有效参考。 ### 回答3: 美国西储大学轴承数据解读 - gshang - 博客园是一篇关于美国西储大学对轴承数据进行解读的博文。据该博文介绍,美国西储大学对轴承数据进行了详细的分析和解读,旨在揭示轴承的性能和机械故障特征,以帮助工程师和研究人员提升机械系统的可靠性和运行效率。 博文中提到,美国西储大学依靠先进的数据采集技术和大数据分析平台,对大量轴承数据进行了收集和整理。通过对数据进行统计和建模分析,研究人员得出了一些重要的结论。 首先,轴承的故障模式和故障频率进行了统计分析。通过对大量故障样本进行观察和记录,研究人员发现,轴承的常见故障模式包括磨损、疲劳和润滑不良等。在故障频率方面,研究人员发现,在特定工况下,轴承的故障频率会有显著的变化。 其次,对轴承的性能指标进行了评估和分析。通过对轴承的运行参数进行录制和分析,如速度、温度和载荷等,研究人员可以评估轴承的性能和工作状态。这些参数对于判断轴承的性能和寿命具有重要的指导意义。 此外,通过对轴承数据进行模型建立和预测分析,研究人员可以对轴承的寿命和预期故障进行估计。这对于设备维护和故障预警具有重要意义,可以帮助工程师和运维人员在故障之前采取相应的措施,降低设备损坏和停机时间。 综上所述,美国西储大学对轴承数据的解读提供了重要的参考和指导,对于轴承的设计、评估和维护有着重要的实际意义。这一研究成果有助于提升机械系统的可靠性和运行效率,减少设备故障和维修成本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值