简体   繁体   English

C ++ / CURL-通过PHP传递数据请求安全的方法?

[英]C++/CURL - Passing data through PHP request the safe way?

I'm trying to send data with curl to my PHP file and then I can do all the other actions like hashing password/data with salt, running database queries eco. 我试图将带有curl的数据发送到我的PHP文件,然后可以执行所有其他操作,例如用salt对密码/数据进行哈希处理,运行数据库查询eco。 It seems to work fine, but there's only one problem. 看来工作正常,但是只有一个问题。 I'm not sure how to secure it, with an authorization token for example. 我不确定如何保护它,例如使用授权令牌。 I want to be able to query data from my PHP file using the written application only. 我只想使用编写的应用程序从我的PHP文件中查询数据。 I can see how this would become a problem, if people had access to the link through web browser for example. 我可以看到,如果人们可以通过Web浏览器访问链接,这将成为一个问题。

I've included my code below, if someone needs something similar. 如果有人需要类似的东西,我将下面的代码包括在内。

main.cpp main.cpp中

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <curl/curl.h>
#include <sha.h>
#include <hex.h>

using namespace std;
using namespace CryptoPP;

size_t size = 0;
size_t write_to_string(void *ptr, size_t size, size_t count, void *stream) {
    ((string*)stream)->append((char*)ptr, 0, size*count);
    return size*count;
}

template <class T>
string QueryDB(initializer_list<T> list) // Use initialize_list to query an undefined number of params
{
    CURL *curl;
    CURLcode res;

    string submitdata = "", query_result;

    int i = 1;
    for (auto elem : list) // For each param append to the submitdata string
    {
        if (i == 1) { // If first param, we append "?"
            string d = "?" + to_string(i) + "=" + elem;
            submitdata.append(d);
        } else if (i > 1) { // If not first param, we append "&" as it's the second, third, fourth ... param
            string d = "&" + to_string(i) + "=" + elem;
            submitdata.append(d);
        }
        i++;
    }

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();

    if (curl)
    {
        string loginurl = string("http://localhost/login.php");

        curl_easy_setopt(curl, CURLOPT_USERPWD, "randomhttpuser:randomhttppassword");
        curl_easy_setopt(curl, CURLOPT_URL, (loginurl + submitdata).c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &query_result);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
        res = curl_easy_perform(curl);

        if (res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        curl_easy_cleanup(curl);
    }
    else {
        query_result = "CONNECTION FAILED";
    }
    curl_global_cleanup();

    return query_result;
}

string SHA256Hash(string input)
{
    SHA256 hash;
    string hashed_input;

    StringSource ss(input, true, new HashFilter(hash, new HexEncoder(new StringSink(hashed_input))));

    return hashed_input;
}

int main()
{
    string username = "testuser";
    string raw_password = "testpass";

    // Hash password and send it as a query to PHP file
    // query_result will hold the value of REQUEST response
    auto hashed_password = SHA256Hash(raw_password);
    auto query_result = QueryDB({ username, hashed_password });

    cout << "=========================================== [ POST ] ===========================================" << endl;
    cout << "User: " << username.c_str() << endl;
    cout << "Raw Password: " << raw_password.c_str() << endl;
    cout << "Hashed password: " << hashed_password.c_str() << endl;
    cout << "========================================== [ REQUEST ] =========================================" << endl;
    cout << query_result.c_str() << endl;


    Sleep(15 * 1000);
    return 0;
}

login.php 的login.php

<?php

$reqparams = array();

function AddStringToArray($name,$string) {
    global $reqparams;
    $reqparams[$name] = $string;
}

/* Check if specified param exists in reqparams array */
function GetRequestParam($value) {
    global $reqparams;

    if (array_key_exists($value, $reqparams)) {
        $returnvalue = $reqparams[$value];
    } else {
        $returnvalue = "INVALID PARAMETER";
    }

    return $returnvalue;
}

$authuser = "randomhttpuser";
$authpw = "randomhttppassword";
$authorized = False;

if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Failed to authorize!';
    exit;
} else {

    if($_SERVER['PHP_AUTH_USER'] == $authuser && $_SERVER['PHP_AUTH_PW'] == $authpw)
    {
        $authorized = True;
    } else {
        $authorized = False;
        die('Failed to authorize!');
    }
}

if($authorized == True)
{
    /* Store each REQUEST and it's value in the $reqparams array using AddStringToArray function */
    foreach ($_REQUEST as $key => $value)  
    {
        $value = addslashes($value);
        $value = strip_tags($value);

        AddStringToArray($key, $value);
    }

    /* You should remember in which order you called the params in your REQUEST query or if you really want, you can just use:

    $variable = $_REQUEST['param_name'];

    However, if an undefined param is specified, it will result in an warning and ruin your output, if you manually parse it */

    $user = GetRequestParam(1);
    $pass = GetRequestParam(2);

    /* GetRequestParam returns 'INVALID_PARAMETER' instead of a warning that an undefined param was requested */
    $invalid_param = GetRequestParam(42);

    /* Re-hash password with a salt that's stored in the PHP file only, before using or comparing it to the value stored in database or doing whatever else */
    $salt = $user . $pass . "secretkey42";
    $salt_hashed_passsword = strtoupper(hash('sha256', $salt));

    echo "User: $user";
    echo "\nHashed Password: $salt_hashed_passsword (Salt)";
}

?>

Edit: I could use HTTP header, but isn't it possible to reverse my application and abuse it? 编辑:我可以使用HTTP标头,但是否有可能会反转我的应用程序并滥用它?

Edit: I currently decided to use HTTP authentication as a temporary measure. 编辑:我目前决定使用HTTP身份验证作为一种临时措施。

I stored a random generated username and password in my PHP file and compare them to the PHP_AUTH_USER/PW which are sent in the HTTP header from my cpp application using CURLOPT_USERPWD: 我在PHP文件中存储了一个随机生成的用户名和密码,并将它们与PHP_AUTH_USER / PW进行比较,后者使用CURLOPT_USERPWD从cpp应用程序的HTTP标头中发送:

curl_easy_setopt(curl, CURLOPT_USERPWD, "randomhttpusername:randomhttppassword");

Hopefully, this will at least make it a bit harder for the hacker. 希望这至少会使黑客更难一点。 First he will have to RE my application to get the the user/password and even after that he can only query the response if password belongs to specified user or not - since most of my queries are hard coded. 首先,他将必须重新申请我的应用程序才能获取用户名/密码,即使在那之后,他也只能查询密码是否属于指定用户的响应-因为我的大多数查询都是硬编码的。 You could even store the number of failed logins and temporarily ban him for x amount of time. 您甚至可以存储登录失败的次数,并在x时间内临时禁止他登录。 Rest of the queries are made after login returns true. 登录返回true后,将进行其余查询。

I've also updated the code above to use the changes I've made and added some comments if you're too lazy to go over the code line-by-line. 我还更新了上面的代码以使用所做的更改,并在您懒得逐行浏览代码时添加了一些注释。 Feel free to give me some tips on how to improve the code or optimize for better use. 请随时给我一些有关如何改进代码或进行优化以更好地使用的提示。

From what I understood, you want to implement a some sort of login system using auth tokens. 据我了解,您想使用auth令牌实现某种登录系统。 In this case, OAuth can do the job. 在这种情况下,OAuth可以完成这项工作。 Here's a tutorial written on SitePoint that can guide you through the process. 这是在SitePoint上写的教程,可以指导您完成整个过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM