Изменение аутентификации libsoup в SoupSession
У меня есть рабочий клиент libsoup, который отправляет данные с помощью HTTP POST и базовой аутентификации. Аутентификация выполняется вlibsoup
через обратный вызов - когда сервер требует аутентификации libsoup
сигнализирует об этом с помощью обратного вызова - а затем функция soup_auth_authenticate()
получает переданный объект типа SoupAuth вместе с именем пользователя и паролем.
#include <iostream>
#include <iomanip>
#include <string>
#include <libsoup/soup.h>
using namespace std;
void authenticate(SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer data) {
soup_auth_authenticate(auth, "foo", "bar");
}
int main() {
SoupSession* session = soup_session_new_with_options(SOUP_SESSION_USER_AGENT, "stackru",
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR,
NULL);
g_signal_connect(session, "authenticate", G_CALLBACK(authenticate), nullptr);
SoupMessage* post_msg = soup_message_new("POST", "https://example.org/work.php");
string formdata = "first_name=Captain&last_name=Picard";
soup_message_set_request(post_msg, "application/x-www-form-urlencoded", SOUP_MEMORY_COPY, formdata.c_str(), formdata.size());
soup_session_send_message(session, post_msg);
cout << left << setw(22) << "status code: " << right << post_msg->status_code << "\n";
cout << left << setw(22) << "reason phrase: " << right << post_msg->reason_phrase << "\n";
cout << left << setw(22) << "response body length: " << right << post_msg->response_body->length << "\n";
cout << left << setw(22) << "response body data: " << right << post_msg->response_body->data << "\n";
// TODO call soup_session_send_message() again with modified username and password
return EXIT_SUCCESS;
}
Вы можете скомпилировать это с помощью g++ -o sample sample.cpp -Wall -pedantic -g `pkg-config libsoup-2.4 --cflags --libs`
. Если вам нужно это проверить, смените домен сexample.org
к flapflap.eu
что даст вам рабочую конечную точку.
Что мне делать, если я хочу отправить другое имя пользователя или пароль в следующем звонке? Библиотека больше не будет использовать обратный вызов, потому что аутентификация уже настроена и работает.
Мне нужно создать новый SoupSession
? Или я могу получить доступ к текущемуSoupAuth
и позвони soup_auth_authenicate()
прямо? Я хочу, чтобы клиент работал быстро.
Спасибо за помощь
1 ответ
The background information at bottom indicates that you do not need to create a new SoupSession
to make subsequent authentication requests. It is not clear though that the soup_auth_authenticate()
call is the method to do that. Following is the list of authentication related calls from this libsoup page:
SoupAuth * soup_auth_new ()
gboolean soup_auth_update ()
gboolean soup_auth_negotiate_supported ()
gboolean soup_auth_is_for_proxy ()
const char * soup_auth_get_scheme_name ()
const char * soup_auth_get_host ()
const char * soup_auth_get_realm ()
char * soup_auth_get_info ()
void soup_auth_authenticate ()
gboolean soup_auth_can_authenticate ()
gboolean soup_auth_is_authenticated ()
gboolean soup_auth_is_ready ()
char * soup_auth_get_authorization ()
GSList * soup_auth_get_protection_space ()
void soup_auth_free_protection_space ()
Reading between the lines in this Basics page seems to suggest it is possible to make multiple authentication requests in a single SoupSession
.
Handling Authentication
SoupSession handles most of the details of HTTP authentication for you. If it receives a 401 ("Unauthorized") or 407 ("Proxy Authentication Required") response, the session will emit the authenticate signal, providing you with a SoupAuth object indicating the authentication type ("Basic", "Digest", or "NTLM") and the realm name provided by the server. If you have a username and password available (or can generate one), call soup_auth_authenticate to give the information to libsoup. The session will automatically requeue the message and try it again with that authentication information. (If you don't call soup_auth_authenticate, the session will just return the message to the application with its 401 or 407 status.)
If the server doesn't accept the username and password provided, the session will emit authenticate again, with the retrying parameter set to TRUE. This lets the application know that the information it provided earlier was incorrect, and gives it a chance to try again. If this username/password pair also doesn't work, the session will contine to emit authenticate again and again until the provided username/password successfully authenticates, or until the signal handler fails to call soup_auth_authenticate, at which point libsoup will allow the message to fail (with status 401 or 407).
If you need to handle authentication asynchronously (eg, to pop up a password dialog without recursively entering the main loop), you can do that as well. Just call soup_session_pause_message on the message before returning from the signal handler, and g_object_ref the SoupAuth. Then, later on, after calling soup_auth_authenticate (or deciding not to), call soup_session_unpause_message to resume the paused message.
This Manpagez post also discusses more than one call to authenticate per session:
Most applications will only need a single SoupSession; the primary reason you might need multiple sessions is if you need to have multiple independent authentication contexts. (Eg, you are connecting to a server and authenticating as two different users at different times; the easiest way to ensure that each SoupMessage is sent with the authentication information you intended is to use one session for the first user, and a second session for the other user.)