10 #include <boost/algorithm/string.hpp> 11 #include <pion/algorithm.hpp> 12 #include <pion/http/cookie_auth.hpp> 13 #include <pion/http/response_writer.hpp> 14 #include <pion/http/server.hpp> 24 const unsigned int cookie_auth::CACHE_EXPIRATION = 3600;
25 const unsigned int cookie_auth::RANDOM_COOKIE_BYTES = 20;
26 const std::string cookie_auth::AUTH_COOKIE_NAME =
"pion_session_id";
32 const std::string& login,
33 const std::string& logout,
34 const std::string& redirect)
35 : http::
auth(userManager), m_login(login), m_logout(logout), m_redirect(redirect),
36 m_random_gen(), m_random_range(0, 255), m_random_die(m_random_gen, m_random_range),
37 m_cache_cleanup_time(boost::posix_time::second_clock::universal_time())
40 set_logger(PION_GET_LOGGER(
"pion.http.cookie_auth"));
46 m_random_gen.seed(static_cast<boost::mt19937::result_type>(::time(NULL)));
49 for (
unsigned int n = 0; n < 100; ++n)
64 if (!m_redirect.empty() && m_redirect==http_request_ptr->get_resource()) {
69 boost::posix_time::ptime time_now(boost::posix_time::second_clock::universal_time());
73 const std::string auth_cookie(http_request_ptr->get_cookie(AUTH_COOKIE_NAME));
74 if (! auth_cookie.empty()) {
76 boost::mutex::scoped_lock cache_lock(m_cache_mutex);
77 user_cache_type::iterator user_cache_itr=m_user_cache.find(auth_cookie);
78 if (user_cache_itr != m_user_cache.end()) {
81 http_request_ptr->set_user(user_cache_itr->second.second);
83 user_cache_itr->second.first = time_now;
97 else if (name==
"logout")
99 else if (name==
"redirect")
102 BOOST_THROW_EXCEPTION(
error::bad_arg() << error::errinfo_arg_name(name) );
110 if (resource != m_login && resource != m_logout) {
114 std::string redirect_url = http_request_ptr->get_query(
"url");
115 std::string new_cookie;
116 bool delete_cookie =
false;
118 if (resource == m_login) {
121 std::string username = http_request_ptr->get_query(
"user");
122 std::string password = http_request_ptr->get_query(
"pass");
133 std::string rand_binary;
134 rand_binary.reserve(RANDOM_COOKIE_BYTES);
135 for (
unsigned int i=0; i<RANDOM_COOKIE_BYTES ; i++) {
136 rand_binary +=
static_cast<unsigned char>(m_random_die());
141 boost::posix_time::ptime time_now(boost::posix_time::second_clock::universal_time());
142 boost::mutex::scoped_lock cache_lock(m_cache_mutex);
143 m_user_cache.insert(std::make_pair(new_cookie,std::make_pair(time_now,user)));
147 const std::string auth_cookie(http_request_ptr->get_cookie(AUTH_COOKIE_NAME));
148 if (! auth_cookie.empty()) {
149 boost::mutex::scoped_lock cache_lock(m_cache_mutex);
150 user_cache_type::iterator user_cache_itr=m_user_cache.find(auth_cookie);
151 if (user_cache_itr!=m_user_cache.end()) {
152 m_user_cache.erase(user_cache_itr);
156 delete_cookie =
true;
160 if (! redirect_url.empty()) {
164 handle_ok(http_request_ptr,tcp_conn,new_cookie,delete_cookie);
172 const tcp::connection_ptr& tcp_conn)
175 if (!m_redirect.empty()) {
181 static const std::string CONTENT =
182 " <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"" 183 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">" 186 "<TITLE>Error</TITLE>" 187 "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\">" 189 "<BODY><H1>401 Unauthorized.</H1></BODY>" 193 writer->get_response().set_status_code(http::types::RESPONSE_CODE_UNAUTHORIZED);
194 writer->get_response().set_status_message(http::types::RESPONSE_MESSAGE_UNAUTHORIZED);
195 writer->write_no_copy(CONTENT);
200 const tcp::connection_ptr& tcp_conn,
201 const std::string &redirection_url,
202 const std::string &new_cookie,
207 static const std::string CONTENT =
208 " <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"" 209 "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">" 212 "<TITLE>Redirect</TITLE>" 213 "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\">" 215 "<BODY><H1>302 Found.</H1></BODY>" 219 writer->get_response().set_status_code(http::types::RESPONSE_CODE_FOUND);
220 writer->get_response().set_status_message(http::types::RESPONSE_MESSAGE_FOUND);
221 writer->get_response().add_header(http::types::HEADER_LOCATION, redirection_url);
227 writer->get_response().delete_cookie(AUTH_COOKIE_NAME,
"");
228 }
else if (!new_cookie.empty()) {
230 writer->get_response().set_cookie(AUTH_COOKIE_NAME, new_cookie,
"");
233 writer->write_no_copy(CONTENT);
238 const tcp::connection_ptr& tcp_conn,
239 const std::string &new_cookie,
246 writer->get_response().set_status_code(http::types::RESPONSE_CODE_NO_CONTENT);
247 writer->get_response().set_status_message(http::types::RESPONSE_MESSAGE_NO_CONTENT);
253 writer->get_response().delete_cookie(AUTH_COOKIE_NAME,
"");
254 }
else if(!new_cookie.empty()) {
256 writer->get_response().set_cookie(AUTH_COOKIE_NAME, new_cookie,
"");
263 if (time_now > m_cache_cleanup_time + boost::posix_time::seconds(CACHE_EXPIRATION)) {
265 boost::mutex::scoped_lock cache_lock(m_cache_mutex);
266 user_cache_type::iterator i;
267 user_cache_type::iterator next=m_user_cache.begin();
268 while (next!=m_user_cache.end()) {
271 if (time_now > i->second.first + boost::posix_time::seconds(CACHE_EXPIRATION)) {
273 m_user_cache.erase(i);
276 m_cache_cleanup_time = time_now;
void handle_unauthorized(const http::request_ptr &http_request_ptr, const tcp::connection_ptr &tcp_conn)
virtual bool handle_request(const http::request_ptr &http_request_ptr, const tcp::connection_ptr &tcp_conn)
user_manager_ptr m_user_manager
container used to manager user objects
static boost::shared_ptr< response_writer > create(const tcp::connection_ptr &tcp_conn, const http::response_ptr &http_response_ptr, finished_handler_t handler=finished_handler_t())
bool process_login(const http::request_ptr &http_request_ptr, const tcp::connection_ptr &tcp_conn)
static std::string strip_trailing_slash(const std::string &str)
void set_logger(logger log_ptr)
sets the logger to be used
bool need_authentication(http::request_ptr const &http_request_ptr) const
void handle_redirection(const http::request_ptr &http_request_ptr, const tcp::connection_ptr &tcp_conn, const std::string &redirection_url, const std::string &new_cookie="", bool delete_cookie=false)
cookie_auth(user_manager_ptr userManager, const std::string &login="/login", const std::string &logout="/logout", const std::string &redirect="")
virtual void set_option(const std::string &name, const std::string &value)
void handle_ok(const http::request_ptr &http_request_ptr, const tcp::connection_ptr &tcp_conn, const std::string &new_cookie="", bool delete_cookie=false)
exception thrown for an invalid configuration argument or option
static bool base64_encode(std::string const &input, std::string &output)
void expire_cache(const boost::posix_time::ptime &time_now)