mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 16:48:06 +02:00
fixed GH #478: HTTPCredentials and HTTPAuthenticationParams support multiple WWW-Authenticate headers
This commit is contained in:
@@ -46,7 +46,7 @@ public:
|
|||||||
explicit HTTPAuthenticationParams(const HTTPRequest& request);
|
explicit HTTPAuthenticationParams(const HTTPRequest& request);
|
||||||
/// See fromRequest() documentation.
|
/// See fromRequest() documentation.
|
||||||
|
|
||||||
explicit HTTPAuthenticationParams(const HTTPResponse& response);
|
HTTPAuthenticationParams(const HTTPResponse& response, const std::string& header = WWW_AUTHENTICATE);
|
||||||
/// See fromResponse() documentation.
|
/// See fromResponse() documentation.
|
||||||
|
|
||||||
virtual ~HTTPAuthenticationParams();
|
virtual ~HTTPAuthenticationParams();
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
/// Throws a InvalidArgumentException if authentication scheme is
|
/// Throws a InvalidArgumentException if authentication scheme is
|
||||||
/// unknown or invalid.
|
/// unknown or invalid.
|
||||||
|
|
||||||
void fromResponse(const HTTPResponse& response);
|
void fromResponse(const HTTPResponse& response, const std::string& header = WWW_AUTHENTICATE);
|
||||||
/// Extracts authentication information from the response and creates
|
/// Extracts authentication information from the response and creates
|
||||||
/// HTTPAuthenticationParams by parsing it.
|
/// HTTPAuthenticationParams by parsing it.
|
||||||
///
|
///
|
||||||
@@ -91,6 +91,8 @@ public:
|
|||||||
/// request or response authentication header.
|
/// request or response authentication header.
|
||||||
|
|
||||||
static const std::string REALM;
|
static const std::string REALM;
|
||||||
|
static const std::string WWW_AUTHENTICATE;
|
||||||
|
static const std::string PROXY_AUTHENTICATE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parse(std::string::const_iterator first, std::string::const_iterator last);
|
void parse(std::string::const_iterator first, std::string::const_iterator last);
|
||||||
|
@@ -52,6 +52,9 @@ public:
|
|||||||
~HTTPDigestCredentials();
|
~HTTPDigestCredentials();
|
||||||
/// Destroys the HTTPDigestCredentials.
|
/// Destroys the HTTPDigestCredentials.
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
/// Resets the HTTPDigestCredentials object to a clean state.
|
||||||
|
|
||||||
void setUsername(const std::string& username);
|
void setUsername(const std::string& username);
|
||||||
/// Sets the username.
|
/// Sets the username.
|
||||||
|
|
||||||
|
@@ -68,6 +68,8 @@ namespace Net {
|
|||||||
|
|
||||||
|
|
||||||
const std::string HTTPAuthenticationParams::REALM("realm");
|
const std::string HTTPAuthenticationParams::REALM("realm");
|
||||||
|
const std::string HTTPAuthenticationParams::WWW_AUTHENTICATE("WWW-Authenticate");
|
||||||
|
const std::string HTTPAuthenticationParams::PROXY_AUTHENTICATE("Proxy-Authenticate");
|
||||||
|
|
||||||
|
|
||||||
HTTPAuthenticationParams::HTTPAuthenticationParams()
|
HTTPAuthenticationParams::HTTPAuthenticationParams()
|
||||||
@@ -87,9 +89,9 @@ HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPRequest& request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPResponse& response)
|
HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPResponse& response, const std::string& header)
|
||||||
{
|
{
|
||||||
fromResponse(response);
|
fromResponse(response, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -126,22 +128,29 @@ void HTTPAuthenticationParams::fromRequest(const HTTPRequest& request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTTPAuthenticationParams::fromResponse(const HTTPResponse& response)
|
void HTTPAuthenticationParams::fromResponse(const HTTPResponse& response, const std::string& header)
|
||||||
{
|
{
|
||||||
if (!response.has("WWW-Authenticate"))
|
NameValueCollection::ConstIterator it = response.find(header);
|
||||||
|
if (it == response.end())
|
||||||
throw NotAuthenticatedException("HTTP response has no authentication header");
|
throw NotAuthenticatedException("HTTP response has no authentication header");
|
||||||
|
|
||||||
const std::string& header = response.get("WWW-Authenticate");
|
bool found = false;
|
||||||
|
while (!found && it != response.end() && icompare(it->first, header) == 0)
|
||||||
if (icompare(header, 0, 6, "Basic ") == 0)
|
|
||||||
{
|
{
|
||||||
parse(header.begin() + 6, header.end());
|
const std::string& header = it->second;
|
||||||
|
if (icompare(header, 0, 6, "Basic ") == 0)
|
||||||
|
{
|
||||||
|
parse(header.begin() + 6, header.end());
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else if (icompare(header, 0, 7, "Digest ") == 0)
|
||||||
|
{
|
||||||
|
parse(header.begin() + 7, header.end());
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
else if (icompare(header, 0, 7, "Digest ") == 0)
|
if (!found) throw NotAuthenticatedException("No Basic or Digest authentication header found");
|
||||||
{
|
|
||||||
parse(header.begin() + 7, header.end());
|
|
||||||
}
|
|
||||||
else throw InvalidArgumentException("Invalid authentication scheme", header);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -57,7 +57,7 @@ void HTTPCredentials::fromUserInfo(const std::string& userInfo)
|
|||||||
extractCredentials(userInfo, username, password);
|
extractCredentials(userInfo, username, password);
|
||||||
setUsername(username);
|
setUsername(username);
|
||||||
setPassword(password);
|
setPassword(password);
|
||||||
// TODO: Reset digest state?
|
_digest.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,13 +69,13 @@ void HTTPCredentials::fromURI(const URI& uri)
|
|||||||
extractCredentials(uri, username, password);
|
extractCredentials(uri, username, password);
|
||||||
setUsername(username);
|
setUsername(username);
|
||||||
setPassword(password);
|
setPassword(password);
|
||||||
// TODO: Reset digest state?
|
_digest.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response)
|
void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response)
|
||||||
{
|
{
|
||||||
for (HTTPResponse::ConstIterator iter = response.find("WWW-Authenticate"); iter != response.end(); ++iter)
|
for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::WWW_AUTHENTICATE); iter != response.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (isBasicCredentials(iter->second))
|
if (isBasicCredentials(iter->second))
|
||||||
{
|
{
|
||||||
@@ -111,7 +111,7 @@ void HTTPCredentials::updateAuthInfo(HTTPRequest& request)
|
|||||||
|
|
||||||
void HTTPCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
|
void HTTPCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
|
||||||
{
|
{
|
||||||
for (HTTPResponse::ConstIterator iter = response.find("Proxy-Authenticate"); iter != response.end(); ++iter)
|
for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::PROXY_AUTHENTICATE); iter != response.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (isBasicCredentials(iter->second))
|
if (isBasicCredentials(iter->second))
|
||||||
{
|
{
|
||||||
|
@@ -104,6 +104,13 @@ HTTPDigestCredentials::~HTTPDigestCredentials()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HTTPDigestCredentials::reset()
|
||||||
|
{
|
||||||
|
_requestAuthParams.clear();
|
||||||
|
_nc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTTPDigestCredentials::setUsername(const std::string& username)
|
void HTTPDigestCredentials::setUsername(const std::string& username)
|
||||||
{
|
{
|
||||||
_username = username;
|
_username = username;
|
||||||
@@ -138,7 +145,7 @@ void HTTPDigestCredentials::updateAuthInfo(HTTPRequest& request)
|
|||||||
|
|
||||||
void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
|
void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
|
||||||
{
|
{
|
||||||
proxyAuthenticate(request, HTTPAuthenticationParams(response));
|
proxyAuthenticate(request, HTTPAuthenticationParams(response, HTTPAuthenticationParams::PROXY_AUTHENTICATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -259,5 +259,4 @@ void HTTPRequest::setCredentials(const std::string& header, const std::string& s
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::Net
|
} } // namespace Poco::Net
|
||||||
|
@@ -145,6 +145,19 @@ void HTTPCredentialsTest::testAuthenticationParams()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HTTPCredentialsTest::testAuthenticationParamsMultipleHeaders()
|
||||||
|
{
|
||||||
|
HTTPResponse response;
|
||||||
|
response.add("WWW-Authenticate", "Unsupported realm=\"TestUnsupported\"");
|
||||||
|
response.add("WWW-Authenticate", "Digest realm=\"TestDigest\", nonce=\"212573bb90170538efad012978ab811f%lu\"");
|
||||||
|
HTTPAuthenticationParams params(response);
|
||||||
|
|
||||||
|
assert (params["realm"] == "TestDigest");
|
||||||
|
assert (params["nonce"] == "212573bb90170538efad012978ab811f%lu");
|
||||||
|
assert (params.size() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTTPCredentialsTest::testDigestCredentials()
|
void HTTPCredentialsTest::testDigestCredentials()
|
||||||
{
|
{
|
||||||
HTTPDigestCredentials creds("user", "s3cr3t");
|
HTTPDigestCredentials creds("user", "s3cr3t");
|
||||||
@@ -231,6 +244,19 @@ void HTTPCredentialsTest::testCredentialsDigest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HTTPCredentialsTest::testCredentialsDigestMultipleHeaders()
|
||||||
|
{
|
||||||
|
HTTPCredentials creds("user", "s3cr3t");
|
||||||
|
HTTPRequest request(HTTPRequest::HTTP_GET, "/digest/");
|
||||||
|
HTTPResponse response;
|
||||||
|
response.add("WWW-Authenticate", "Unsupported realm=\"TestUnsupported\"");
|
||||||
|
response.add("WWW-Authenticate", "Digest realm=\"TestDigest\", nonce=\"212573bb90170538efad012978ab811f%lu\"");
|
||||||
|
creds.authenticate(request, response);
|
||||||
|
std::string auth = request.get("Authorization");
|
||||||
|
assert (auth == "Digest username=\"user\", nonce=\"212573bb90170538efad012978ab811f%lu\", realm=\"TestDigest\", uri=\"/digest/\", response=\"40e4889cfbd0e561f71e3107a2863bc4\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HTTPCredentialsTest::testProxyCredentialsDigest()
|
void HTTPCredentialsTest::testProxyCredentialsDigest()
|
||||||
{
|
{
|
||||||
HTTPCredentials creds("user", "s3cr3t");
|
HTTPCredentials creds("user", "s3cr3t");
|
||||||
@@ -299,11 +325,13 @@ CppUnit::Test* HTTPCredentialsTest::suite()
|
|||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyBasicCredentials);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyBasicCredentials);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testBadCredentials);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testBadCredentials);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testAuthenticationParams);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testAuthenticationParams);
|
||||||
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testAuthenticationParamsMultipleHeaders);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentials);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentials);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentialsQoP);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentialsQoP);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsBasic);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsBasic);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyCredentialsBasic);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyCredentialsBasic);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsDigest);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsDigest);
|
||||||
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsDigestMultipleHeaders);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyCredentialsDigest);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyCredentialsDigest);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testExtractCredentials);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testExtractCredentials);
|
||||||
CppUnit_addTest(pSuite, HTTPCredentialsTest, testVerifyAuthInfo);
|
CppUnit_addTest(pSuite, HTTPCredentialsTest, testVerifyAuthInfo);
|
||||||
|
@@ -30,11 +30,13 @@ public:
|
|||||||
void testProxyBasicCredentials();
|
void testProxyBasicCredentials();
|
||||||
void testBadCredentials();
|
void testBadCredentials();
|
||||||
void testAuthenticationParams();
|
void testAuthenticationParams();
|
||||||
|
void testAuthenticationParamsMultipleHeaders();
|
||||||
void testDigestCredentials();
|
void testDigestCredentials();
|
||||||
void testDigestCredentialsQoP();
|
void testDigestCredentialsQoP();
|
||||||
void testCredentialsBasic();
|
void testCredentialsBasic();
|
||||||
void testProxyCredentialsBasic();
|
void testProxyCredentialsBasic();
|
||||||
void testCredentialsDigest();
|
void testCredentialsDigest();
|
||||||
|
void testCredentialsDigestMultipleHeaders();
|
||||||
void testProxyCredentialsDigest();
|
void testProxyCredentialsDigest();
|
||||||
void testExtractCredentials();
|
void testExtractCredentials();
|
||||||
void testVerifyAuthInfo();
|
void testVerifyAuthInfo();
|
||||||
|
Reference in New Issue
Block a user