1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

API: Support HTTP basic authentication for API. v6.0.4, v5.0.152 (#3458)

PICK 771ae0a1a6

Co-authored-by: winlin <winlin@vip.126.com>
Co-authored-by: john <hondaxiao@tencent.com>
This commit is contained in:
Haibo Chen 2023-04-01 12:45:29 +08:00 committed by winlin
parent 41decbae95
commit 12f3a31175
14 changed files with 658 additions and 49 deletions

View file

@ -24,6 +24,9 @@ using namespace std;
// @see ISrsHttpMessage._http_ts_send_buffer
#define SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
#define SRS_HTTP_AUTH_SCHEME_BASIC "Basic"
#define SRS_HTTP_AUTH_PREFIX_BASIC SRS_HTTP_AUTH_SCHEME_BASIC " "
// get the status text of code.
string srs_generate_http_status_text(int status)
{
@ -861,22 +864,20 @@ bool SrsHttpServeMux::path_match(string pattern, string path)
return false;
}
SrsHttpCorsMux::SrsHttpCorsMux()
SrsHttpCorsMux::SrsHttpCorsMux(ISrsHttpHandler* h)
{
next = NULL;
enabled = false;
required = false;
next_ = h;
}
SrsHttpCorsMux::~SrsHttpCorsMux()
{
}
srs_error_t SrsHttpCorsMux::initialize(ISrsHttpServeMux* worker, bool cros_enabled)
srs_error_t SrsHttpCorsMux::initialize(bool cros_enabled)
{
next = worker;
enabled = cros_enabled;
return srs_success;
}
@ -918,9 +919,89 @@ srs_error_t SrsHttpCorsMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessag
}
return w->final_request();
}
srs_assert(next);
return next->serve_http(w, r);
return next_->serve_http(w, r);
}
SrsHttpAuthMux::SrsHttpAuthMux(ISrsHttpHandler* h)
{
next_ = h;
enabled_ = false;
}
SrsHttpAuthMux::~SrsHttpAuthMux()
{
}
srs_error_t SrsHttpAuthMux::initialize(bool enabled, std::string username, std::string password)
{
enabled_ = enabled;
username_ = username;
password_ = password;
return srs_success;
}
srs_error_t SrsHttpAuthMux::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
srs_error_t err;
if ((err = do_auth(w, r)) != srs_success) {
srs_error("do_auth %s", srs_error_desc(err).c_str());
srs_freep(err);
w->write_header(SRS_CONSTS_HTTP_Unauthorized);
return w->final_request();
}
srs_assert(next_);
return next_->serve_http(w, r);
}
srs_error_t SrsHttpAuthMux::do_auth(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
srs_error_t err = srs_success;
if (!enabled_) {
return err;
}
// We only apply for api starts with /api/ for HTTP API.
// We don't apply for other apis such as /rtc/, for which we use http callback.
if (r->path().find("/api/") == std::string::npos) {
return err;
}
std::string auth = r->header()->get("Authorization");
if (auth.empty()) {
w->header()->set("WWW-Authenticate", SRS_HTTP_AUTH_SCHEME_BASIC);
return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "empty Authorization");
}
if (!srs_string_contains(auth, SRS_HTTP_AUTH_PREFIX_BASIC)) {
return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "invalid auth %s, should start with %s", auth.c_str(), SRS_HTTP_AUTH_PREFIX_BASIC);
}
std::string token = srs_erase_first_substr(auth, SRS_HTTP_AUTH_PREFIX_BASIC);
if (token.empty()) {
return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "empty token from auth %s", auth.c_str());
}
std::string plaintext;
if ((err = srs_av_base64_decode(token, plaintext)) != srs_success) {
return srs_error_wrap(err, "decode token %s", token.c_str());
}
// The token format must be username:password
std::vector<std::string> user_pwd = srs_string_split(plaintext, ":");
if (user_pwd.size() != 2) {
return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "invalid token %s", plaintext.c_str());
}
if (username_ != user_pwd[0] || password_ != user_pwd[1]) {
w->header()->set("WWW-Authenticate", SRS_HTTP_AUTH_SCHEME_BASIC);
return srs_error_new(SRS_CONSTS_HTTP_Unauthorized, "invalid token %s:%s", user_pwd[0].c_str(), user_pwd[1].c_str());
}
return err;
}
ISrsHttpMessage::ISrsHttpMessage()