Аутентификация C ++ против PHP с помощью cURL - PullRequest
0 голосов
/ 26 августа 2018

Я пытаюсь заставить мое приложение c ++ аутентифицировать пользователя / проходить по веб-базе данных. Для этого у меня есть простая html форма для user / pass, которая запускает скрипт php аутентификации.

Мне трудно понять cURL, так как я полный нуб на нем. Прямо сейчас я могу отправить данные в HTML-форму, но я даже не знаю, правильно ли я делаю.

В идеале, я бы хотел, чтобы вы научили меня, как это делать, и как читать ответ. Я имею в виду, если логин идет правильно, как мне заставить C ++ узнать это?

Весь код, который у меня есть:

HTML

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form method="post" action="check.php">
    <input type="text" name="uname"/>
    <input type="password" name="password"/>
    <input type="submit"/>
</form>
</html>

PHP

<?php
$fileDir = '/var/www/html/forums/';
require($fileDir . '/src/XF.php');
XF::start($fileDir);
$app = \XF::setupAPP('XF\App');

$username = $_POST['uname']; $password = $_POST['password'];

$ip = $app->request->getIp();
$loginService = $app->service('XF:User\Login', $username, $ip);

$userValidate = $loginService->validate($password, $error);
if(!$userValidate)
{
    //Not good pass / user
    $data = ['validated' => false];
}
else $data = ['validated' => true];

header('Content-type: application/json');
echo json_encode($data);
?>

C ++

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <curl/curl.h>

using namespace std;

int main()
{
char username[20];
char password[25];

cout << "Username: ";
cin >> username;
cout << "Password: ";
cin >> password;

/*------------------------------------------*/

CURL *curl;
CURLcode res;

curl_global_init(CURL_GLOBAL_ALL);

curl = curl_easy_init();
if (curl) {
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_URL, "https://localhost/index.hmtl");
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "uname=?&password=?", username, password);

    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);
}
curl_global_cleanup();
}

РЕДАКТИРОВАТЬ: РАБОЧЕЕ РЕШЕНИЕ

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <curl/curl.h>

using namespace std;

string urlencode(const string &str) {
char *escaped = curl_escape(str.c_str(), str.length());
if (escaped == NULL) throw runtime_error("curl_escape failed!");

string ret = escaped;
curl_free(escaped);
return ret;
}

size_t my_write_function(const void * indata, const size_t size, const    size_t count, void *out) {
(*(string*)out).append((const char*)indata, size*count);
return size * count;
}

int main()
{
string username;
string password;

cout << "Username: ";
getline(cin, username);
cout << "Password: ";
getline(cin, password);

/*------------------------------------------*/

CURL *curl;
CURLcode res;

curl_global_init(CURL_GLOBAL_ALL);

curl = curl_easy_init();
if (curl) {
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_URL, "https://urlto/index.html");
    curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, string("uname=" + urlencode(username) + "&password=" + urlencode(password)).c_str());

    string response;
    curl_easy_setopt(curl, CURLOPT_URL, "https://urlto/check.php");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_function);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
    res = curl_easy_perform(curl);

    //cout << "Response from website: " << response << endl;
    if (response.find("true") == string::npos) {
        cout << "Failed to login";
    }
    else cout << "Log in successful";

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

1 Ответ

0 голосов
/ 26 августа 2018

i dont even know if im doing properly. - ну, конечно, в вашем коде есть пара ошибок,

во-первых, что, по вашему мнению, произойдет, если имя пользователя длиннее 20 байтов или пароль длиннее 25 байтов? попробовать

string username;
getline(cin, username);

вместо этого. C ++ будет увеличивать размер имени пользователя по мере необходимости, пока у вас не закончится память, как и должно быть.

и я вижу, что вы используете CURLOPT_POSTFIELDS (и неправильно), пока вы не узнаете, что делаете, я рекомендую вместо этого использовать CURLOPT_COPYPOSTFIELDS. (кстати, я почти всегда сам использую COPYPOSTFIELDS) эта строка неверна:

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "uname=?&password=?", username, password);` 

потому что curl_easy_setopt () принимает только 3 параметра, но вы пытаетесь задать его 5. Я не думаю, что он даже скомпилируется, но даже если это произойдет, он определенно не должен работать во время выполнения. вместо этого попробуйте что-то вроде:

string urlencode(const string& str)
{
    char *escaped = curl_escape(str.c_str(), str.length());
    if (unlikely(escaped==NULL))
    {
        throw runtime_error("curl_escape failed!");
    }
    string ret = escaped;
    curl_free(escaped);
    return ret;
}

curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, string("uname="+urlencode(username)+"&password="+urlencode(password)).c_str());

Что касается чтения (и захвата) вывода, есть много способов сделать это, но как насчет перехвата CURLOPT_WRITEFUNCTION? это имеет тенденцию работать, что-то вроде:

size_t my_write_function( const void * indata, const size_t size, const size_t count, void *out){
    (*(string*)out).append((const char*)indata,size*count);
    return size*count;
}

тогда

string response;
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,my_write_function);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&response);
    res = curl_easy_perform(curl);
cout << "response from website: " << response << endl;

теперь вы можете проверить, вошли ли вы в систему или нет, проверив наличие в ответе строки «true» (потому что она должна отвечать что-то вроде {validated:true}, если вы есть), например,

if(response.find("true")==string::npos){
    cout << "failed to authenticate!";
}else{
    cout << "authenticated successfully!";
}

(и предупреждение, хотя может быть заманчивым использовать лямбда-колбэк с CURLOPT_WRITEFUNCTION, это ловушка, лямбда-символы c ++ могут вылетать, когда передаются curl в качестве колбэков ... были там, сделали это.)

...