mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
Added support for other Authorization-Types then Basic
This commit is contained in:
parent
f402f3da21
commit
fef2469526
@ -135,8 +135,14 @@ __body = oatpp::web::protocol::http::outgoing::BufferBody::createShared(OATPP_MA
|
||||
|
||||
// AUTHORIZATION MACRO
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION(TYPE, NAME) \
|
||||
__headers->put("Authorization", String("Basic ")+oatpp::encoding::Base64::encode(NAME));
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION_1(TYPE, TOKEN) \
|
||||
__headers->put("Authorization", String("Basic ")+oatpp::encoding::Base64::encode(TOKEN));
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION_2(TYPE, TOKEN, SCHEME) \
|
||||
__headers->put("Authorization", String(SCHEME " ") + String(TOKEN));
|
||||
|
||||
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION(TYPE, PARAM_LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
|
||||
|
||||
// FOR EACH
|
||||
|
||||
|
@ -277,13 +277,31 @@ if(NAME.get() == nullptr) { \
|
||||
auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \
|
||||
if(!__param_str_val_##NAME){ \
|
||||
auto error = ApiController::handleError(Status::CODE_401, "Missing HEADER parameter 'Authorization'"); \
|
||||
error->putHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE, "Basic realm=\"" #REALM "\""); \
|
||||
error->putHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE, "Basic realm=\"" REALM "\""); \
|
||||
return error; \
|
||||
} \
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = authorize(__param_str_val_##NAME); \
|
||||
if(__param_aosp_val_##NAME.get() == nullptr) { \
|
||||
auto error = ApiController::handleError(Status::CODE_401, "Unauthorized"); \
|
||||
error->putHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE, "Basic realm=\"" #REALM "\""); \
|
||||
error->putHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE, "Basic realm=\"" REALM "\""); \
|
||||
return error; \
|
||||
} \
|
||||
TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME); \
|
||||
if(NAME.get() == nullptr) { \
|
||||
return ApiController::handleError(Status::CODE_500, "Unable to cast authorization result to '" #TYPE "'"); \
|
||||
}
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_3(TYPE, NAME, REALM, SCHEME) \
|
||||
auto __param_str_val_##NAME = __request->getHeader(oatpp::web::protocol::http::Header::AUTHORIZATION); \
|
||||
if(!__param_str_val_##NAME){ \
|
||||
auto error = ApiController::handleError(Status::CODE_401, "Missing HEADER parameter 'Authorization'"); \
|
||||
error->putHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE, SCHEME " realm=\"" REALM "\""); \
|
||||
return error; \
|
||||
} \
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> __param_aosp_val_##NAME = authorize(__param_str_val_##NAME); \
|
||||
if(__param_aosp_val_##NAME.get() == nullptr) { \
|
||||
auto error = ApiController::handleError(Status::CODE_401, "Unauthorized"); \
|
||||
error->putHeader(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE, SCHEME " realm=\"" REALM "\""); \
|
||||
return error; \
|
||||
} \
|
||||
TYPE NAME = std::static_pointer_cast<TYPE::element_type>(__param_aosp_val_##NAME); \
|
||||
@ -297,10 +315,16 @@ OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATI
|
||||
// __INFO
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1(TYPE, NAME) \
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType());
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \
|
||||
info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = "Basic";
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2(TYPE, NAME, REALM) \
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType());
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \
|
||||
info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = "Basic";
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_3(TYPE, NAME, REALM, SCHEME) \
|
||||
info->headers.add(oatpp::web::protocol::http::Header::AUTHORIZATION, oatpp::String::Class::getType()); \
|
||||
info->headers[oatpp::web::protocol::http::Header::AUTHORIZATION].description = SCHEME;
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO(TYPE, PARAM_LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
|
||||
|
@ -99,6 +99,9 @@
|
||||
|
||||
// AUTHORIZATION MACRO
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION_1
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION_2
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_AUTHORIZATION
|
||||
|
||||
// FOR EACH
|
||||
|
@ -130,11 +130,13 @@
|
||||
// AUTHORIZATION MACRO // ------------------------------------------------------
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_1
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_2
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_3
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION
|
||||
|
||||
// __INFO
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_1
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_2
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO_3
|
||||
#undef OATPP_MACRO_API_CONTROLLER_AUTHORIZATION_INFO
|
||||
|
||||
// FOR EACH // ------------------------------------------------------
|
||||
|
@ -48,6 +48,7 @@ add_executable(oatppAllTests
|
||||
oatpp/web/FullTest.cpp
|
||||
oatpp/web/FullTest.hpp
|
||||
oatpp/web/app/Client.hpp
|
||||
oatpp/web/app/BearerAuthorizationController.hpp
|
||||
oatpp/web/app/AuthorizationController.hpp
|
||||
oatpp/web/app/Controller.hpp
|
||||
oatpp/web/app/ControllerAsync.hpp
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "oatpp/web/app/Controller.hpp"
|
||||
#include "oatpp/web/app/AuthorizationController.hpp"
|
||||
#include "oatpp/web/app/BearerAuthorizationController.hpp"
|
||||
|
||||
#include "oatpp/web/client/HttpRequestExecutor.hpp"
|
||||
|
||||
@ -140,6 +141,7 @@ void FullTest::onRun() {
|
||||
|
||||
runner.addController(app::Controller::createShared());
|
||||
runner.addController(app::AuthorizationController::createShared());
|
||||
runner.addController(app::BearerAuthorizationController::createShared());
|
||||
|
||||
runner.run([this, &runner] {
|
||||
|
||||
@ -228,17 +230,18 @@ void FullTest::onRun() {
|
||||
}
|
||||
|
||||
{ // test simple authorization header
|
||||
auto response = client->defauthorization("foo:bar", connection);
|
||||
auto response = client->defAuthorization("foo:bar", connection);
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test authorzation of unknown user in endpoint-code
|
||||
auto response = client->defauthorization("john:doe");
|
||||
oatpp::String token = "john:doe"; // this time as string to test Macro generation
|
||||
auto response = client->defAuthorization(token);
|
||||
OATPP_ASSERT(response->getStatusCode() == 403);
|
||||
}
|
||||
|
||||
{ // test call of an endpoint that requiers authorization headers, but we don't send one
|
||||
auto response = client->defauthorizationWithoutHeader();
|
||||
auto response = client->defAuthorizationWithoutHeader();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
@ -252,18 +255,18 @@ void FullTest::onRun() {
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with default authorization object
|
||||
auto response = client->mydefauthorization("foo:bar", connection);
|
||||
auto response = client->myDefAuthorization("foo:bar", connection);
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object
|
||||
auto response = client->myauthorization("foo:bar", connection);
|
||||
auto response = client->myAuthorization("foo:bar", connection);
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object with unknown credentials where the
|
||||
// handler returns nullptr
|
||||
auto response = client->myauthorization("john:doe");
|
||||
auto response = client->myAuthorization("john:doe");
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
@ -273,7 +276,45 @@ void FullTest::onRun() {
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end())
|
||||
OATPP_ASSERT(header->second.toString()->startsWith("Basic realm="))
|
||||
OATPP_ASSERT(header->second.toString()->startsWith("Basic realm=\"API\""))
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object with unknown credentials where the
|
||||
// handler returns nullptr and we set a custom realm
|
||||
auto response = client->myAuthorizationRealm("john:doe");
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
"code=401\n"
|
||||
"description=Unauthorized\n"
|
||||
"message=Unauthorized\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end())
|
||||
OATPP_ASSERT(header->second.toString()->startsWith("Basic realm=\"Test Realm\""))
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization method
|
||||
oatpp::String token = "4e99e8c12de7e01535248d2bac85e732";
|
||||
auto response = client->bearerAuthorization(token);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 200);
|
||||
}
|
||||
|
||||
{ // test custom authorization handler with custom authorization object with unknown credentials where the
|
||||
// handler returns nullptr
|
||||
oatpp::String token = "900150983cd24fb0d6963f7d28e17f72";
|
||||
auto response = client->bearerAuthorization(token);
|
||||
oatpp::String body = response->readBodyToString();
|
||||
OATPP_ASSERT(response->getStatusCode() == 401);
|
||||
OATPP_ASSERT(body == "server=oatpp/" OATPP_VERSION "\n"
|
||||
"code=401\n"
|
||||
"description=Unauthorized\n"
|
||||
"message=Unauthorized\n");
|
||||
// should also add the WWW-Authenticate header when Authorization is missing or wrong
|
||||
auto header = response->getHeaders().find(oatpp::web::protocol::http::Header::WWW_AUTHENTICATE);
|
||||
OATPP_ASSERT(header != response->getHeaders().end())
|
||||
OATPP_ASSERT(header->second.toString()->startsWith("Bearer realm=\"Bearer Realm\""))
|
||||
}
|
||||
|
||||
{ // test Chunked body
|
||||
|
@ -104,6 +104,16 @@ class AuthorizationController : public oatpp::web::server::api::ApiController {
|
||||
}
|
||||
}
|
||||
|
||||
ENDPOINT("GET", "myauthorizationrealm", myauthorizationrealm,
|
||||
AUTHORIZATION(std::shared_ptr<MyAuthorizationObject>, authorizationHeader, "Test Realm")) {
|
||||
auto dto = TestDto::createShared();
|
||||
dto->testValue = authorizationHeader->user + ":" + authorizationHeader->password;
|
||||
if(dto->testValue == "foo:bar" && authorizationHeader->id == oatpp::Int64(1337)) {
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
} else {
|
||||
return createDtoResponse(Status::CODE_401, dto);
|
||||
}
|
||||
}
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
|
||||
};
|
||||
|
109
test/oatpp/web/app/BearerAuthorizationController.hpp
Normal file
109
test/oatpp/web/app/BearerAuthorizationController.hpp
Normal file
@ -0,0 +1,109 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
* Benedikt-Alexander Mokroß <bam@icognize.de>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef oatpp_test_web_app_BearerAuthorizationController_hpp
|
||||
#define oatpp_test_web_app_BearerAuthorizationController_hpp
|
||||
|
||||
#include "./DTOs.hpp"
|
||||
|
||||
#include "oatpp/web/mime/multipart/FileStreamProvider.hpp"
|
||||
#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp"
|
||||
#include "oatpp/web/mime/multipart/Reader.hpp"
|
||||
|
||||
#include "oatpp/web/protocol/http/outgoing/MultipartBody.hpp"
|
||||
#include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp"
|
||||
|
||||
#include "oatpp/web/server/api/ApiController.hpp"
|
||||
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
|
||||
#include "oatpp/core/utils/ConversionUtils.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
#include "oatpp/core/macro/component.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace oatpp { namespace test { namespace web { namespace app {
|
||||
|
||||
class BearerAuthorizationObject : public oatpp::web::server::handler::AuthorizationObject {
|
||||
public:
|
||||
oatpp::String token;
|
||||
};
|
||||
|
||||
class BearerAuthorizationHandler : public oatpp::web::server::handler::AuthorizationHandler {
|
||||
public:
|
||||
std::shared_ptr<oatpp::web::server::handler::AuthorizationObject> handleAuthorization(const oatpp::String &header) override {
|
||||
if(!header->startsWith("Bearer ")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
oatpp::String token = (const char*)(header->c_str() + 7);
|
||||
// foo:bar = 4e99e8c12de7e01535248d2bac85e732
|
||||
|
||||
if(token == "4e99e8c12de7e01535248d2bac85e732") {
|
||||
auto obj = std::make_shared<BearerAuthorizationObject>();
|
||||
obj->user = "foo";
|
||||
obj->password = "bar";
|
||||
obj->token = token;
|
||||
return obj;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class BearerAuthorizationController : public oatpp::web::server::api::ApiController {
|
||||
private:
|
||||
static constexpr const char* TAG = "test::web::app::BearerAuthorizationController";
|
||||
|
||||
public:
|
||||
BearerAuthorizationController(const std::shared_ptr<ObjectMapper>& objectMapper)
|
||||
: oatpp::web::server::api::ApiController(objectMapper)
|
||||
{
|
||||
m_authorizationHandler = std::make_shared<BearerAuthorizationHandler>();
|
||||
}
|
||||
public:
|
||||
|
||||
static std::shared_ptr<BearerAuthorizationController> createShared(const std::shared_ptr<ObjectMapper>& objectMapper = OATPP_GET_COMPONENT(std::shared_ptr<ObjectMapper>)){
|
||||
return std::make_shared<BearerAuthorizationController>(objectMapper);
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
|
||||
ENDPOINT("GET", "bearerauthorization", authorization,
|
||||
AUTHORIZATION(std::shared_ptr<BearerAuthorizationObject>, authorizatioBearer, "Bearer Realm", "Bearer")) {
|
||||
auto dto = TestDto::createShared();
|
||||
dto->testValue = authorizatioBearer->user + ":" + authorizatioBearer->password;
|
||||
if(dto->testValue == "foo:bar" && authorizatioBearer->token == "4e99e8c12de7e01535248d2bac85e732") {
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
} else {
|
||||
return createDtoResponse(Status::CODE_401, dto);
|
||||
}
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_END(ApiController)
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* oatpp_test_web_app_Controller_hpp */
|
@ -49,10 +49,12 @@ public:
|
||||
API_CALL("POST", "body", postBody, BODY_STRING(String, body))
|
||||
API_CALL("POST", "echo", echoBody, BODY_STRING(String, body))
|
||||
API_CALL("GET", "header-value-set", headerValueSet, HEADER(String, valueSet, "X-VALUE-SET"))
|
||||
API_CALL("GET", "defauthorization", defauthorization, AUTHORIZATION(String, authorization))
|
||||
API_CALL("GET", "defauthorization", defauthorizationWithoutHeader)
|
||||
API_CALL("GET", "mydefauthorization", mydefauthorization, AUTHORIZATION(String, authorization))
|
||||
API_CALL("GET", "myauthorization", myauthorization, AUTHORIZATION(String, authorization))
|
||||
API_CALL("GET", "defauthorization", defAuthorization, AUTHORIZATION(String, authorization))
|
||||
API_CALL("GET", "defauthorization", defAuthorizationWithoutHeader)
|
||||
API_CALL("GET", "mydefauthorization", myDefAuthorization, AUTHORIZATION(String, authorization))
|
||||
API_CALL("GET", "myauthorization", myAuthorization, AUTHORIZATION(String, authorization))
|
||||
API_CALL("GET", "myauthorizationrealm", myAuthorizationRealm, AUTHORIZATION(String, authorization));
|
||||
API_CALL("GET", "bearerauthorization", bearerAuthorization, AUTHORIZATION(String, authorization, "Bearer"))
|
||||
API_CALL("GET", "chunked/{text-value}/{num-iterations}", getChunked, PATH(String, text, "text-value"), PATH(Int32, numIterations, "num-iterations"))
|
||||
API_CALL("POST", "test/multipart/{chunk-size}", multipartTest, PATH(Int32, chunkSize, "chunk-size"), BODY(std::shared_ptr<MultipartBody>, body))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user