void LoggingHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) { bool reauth = true; if (request.hasCredentials()) { std::string cred; std::string scheme; try { Poco::Net::HTTPBasicCredentials cred(request); std::string user = cred.getUsername(); std::istringstream istr(cred.getPassword(), std::ios::binary); Poco::MD5Engine md5; Poco::DigestOutputStream dos(md5); Poco::StreamCopier::copyStream(istr, dos); dos.close(); std::string pwd = Poco::DigestEngine::digestToHex(md5.digest()); reauth = (pwd != _pwdHash || _user != user); } catch (...) { reauth = true; } } if (reauth) { response.requireAuthentication(TITLE); response.send(); return; } Poco::Net::HTMLForm form(request); std::string offsetStr; Poco::Net::NameValueCollection::ConstIterator it = form.find(OFFSET); if (it != form.end()) offsetStr = it->second; int offset(0); Poco::NumberParser::tryParse(offsetStr, offset); std::string numEntriesStr; it = form.find(NUMENTRIES); if (it != form.end()) numEntriesStr = it->second; int numEntries = DEFAULT_NUMENTRIES; Poco::NumberParser::tryParse(numEntriesStr, numEntries); std::vector<Poco::Message> messages; _channel.getMessages(messages, offset, numEntries); displayMessages(messages, offset, numEntries, _channel.getCurrentSize(), response); }
void HTTPHandler::processQuery( Poco::Net::HTTPServerRequest & request, HTMLForm & params, Poco::Net::HTTPServerResponse & response, Output & used_output) { Context context = server.context(); context.setGlobalContext(server.context()); CurrentThread::QueryScope query_scope(context); LOG_TRACE(log, "Request URI: " << request.getURI()); std::istream & istr = request.stream(); /// Part of the query can be passed in the 'query' parameter and the rest in the request body /// (http method need not necessarily be POST). In this case the entire query consists of the /// contents of the 'query' parameter, a line break and the request body. std::string query_param = params.get("query", ""); if (!query_param.empty()) query_param += '\n'; /// The user and password can be passed by headers (similar to X-Auth-*), /// which is used by load balancers to pass authentication information. std::string user = request.get("X-ClickHouse-User", ""); std::string password = request.get("X-ClickHouse-Key", ""); std::string quota_key = request.get("X-ClickHouse-Quota", ""); if (user.empty() && password.empty() && quota_key.empty()) { /// User name and password can be passed using query parameters /// or using HTTP Basic auth (both methods are insecure). if (request.hasCredentials()) { Poco::Net::HTTPBasicCredentials credentials(request); user = credentials.getUsername(); password = credentials.getPassword(); } else { user = params.get("user", "default"); password = params.get("password", ""); } quota_key = params.get("quota_key", ""); } else { /// It is prohibited to mix different authorization schemes. if (request.hasCredentials() || params.has("user") || params.has("password") || params.has("quota_key")) { throw Exception("Invalid authentication: it is not allowed to use X-ClickHouse HTTP headers and other authentication methods simultaneously", ErrorCodes::REQUIRED_PASSWORD); } } std::string query_id = params.get("query_id", ""); context.setUser(user, password, request.clientAddress(), quota_key); context.setCurrentQueryId(query_id); /// The user could specify session identifier and session timeout. /// It allows to modify settings, create temporary tables and reuse them in subsequent requests. std::shared_ptr<Context> session; String session_id; std::chrono::steady_clock::duration session_timeout; bool session_is_set = params.has("session_id"); const auto & config = server.config(); if (session_is_set) { session_id = params.get("session_id"); session_timeout = parseSessionTimeout(config, params); std::string session_check = params.get("session_check", ""); session = context.acquireSession(session_id, session_timeout, session_check == "1"); context = *session; context.setSessionContext(*session); } SCOPE_EXIT({ if (session_is_set) session->releaseSession(session_id, session_timeout); });