update cookie lifetime.
All checks were successful
Deploy / Build (push) Successful in 7m23s

This commit is contained in:
amass 2025-01-03 14:12:02 +08:00
parent 769e672ca0
commit c3f535e82e
10 changed files with 107 additions and 4 deletions

View File

@ -14,7 +14,7 @@ Live2dBackend::Live2dBackend() {
using namespace boost::beast; using namespace boost::beast;
boost::urls::url_view view(request.target()); boost::urls::url_view view(request.target());
auto target = view.path(); auto target = view.path();
LOG(info) << target; // LOG(info) << target;
if (target.find("..") != boost::beast::string_view::npos) { if (target.find("..") != boost::beast::string_view::npos) {
session.reply(ServiceLogic::badRequest(request, "Illegal request-target")); session.reply(ServiceLogic::badRequest(request, "Illegal request-target"));
return; return;

View File

@ -7,6 +7,7 @@
#include "NavigationBar.h" #include "NavigationBar.h"
#include "Restful.h" #include "Restful.h"
#include "VisitorRecordsPage.h" #include "VisitorRecordsPage.h"
#include "model/AuthModel.h"
#include <Wt/Auth/AuthService.h> #include <Wt/Auth/AuthService.h>
#include <Wt/Auth/HashFunction.h> #include <Wt/Auth/HashFunction.h>
#include <Wt/Auth/Identity.h> #include <Wt/Auth/Identity.h>
@ -113,6 +114,8 @@ void Application::authEvent() {
auto token = env.getCookie(service.authTokenCookieName()); auto token = env.getCookie(service.authTokenCookieName());
if (token == nullptr) { if (token == nullptr) {
Wt::Http::Cookie cookie(service.authTokenCookieName(), service.createAuthToken(u)); Wt::Http::Cookie cookie(service.authTokenCookieName(), service.createAuthToken(u));
cookie.setPath(AuthModel::CookiePath);
cookie.setExpires(Wt::WDateTime());
setCookie(cookie); setCookie(cookie);
} }
} else { } else {
@ -187,7 +190,7 @@ void Server::initializeAuthenticationService() {
m_authService = std::make_unique<Wt::Auth::AuthService>(); m_authService = std::make_unique<Wt::Auth::AuthService>();
m_authService->setEmailVerificationEnabled(true); m_authService->setEmailVerificationEnabled(true);
m_authService->setEmailVerificationRequired(true); m_authService->setEmailVerificationRequired(true);
m_authService->setAuthTokensEnabled(true, "logincookie"); m_authService->setAuthTokensEnabled(true);
m_passwordService = std::make_unique<Wt::Auth::PasswordService>(*m_authService); m_passwordService = std::make_unique<Wt::Auth::PasswordService>(*m_authService);
auto verifier = std::make_unique<Wt::Auth::PasswordVerifier>(); auto verifier = std::make_unique<Wt::Auth::PasswordVerifier>();
@ -204,4 +207,37 @@ Wt::Auth::AuthService &Server::authService() {
const Wt::Auth::PasswordService &Server::passwordService() { const Wt::Auth::PasswordService &Server::passwordService() {
return *m_passwordService; return *m_passwordService;
} }
void Server::insertCookie(const std::string &cookie) {
if (!m_cookies.contains(cookie)) {
m_cookies.insert(cookie);
}
}
Wt::Http::Cookie Server::updateCookie(const std::string &oldCookie, const Wt::Auth::AuthTokenResult &result, bool secure) {
Wt::Http::Cookie cookie(m_authService->authTokenCookieName());
cookie.setPath(AuthModel::CookiePath);
cookie.setSecure(secure);
if (result.state() == Wt::Auth::AuthTokenState::Invalid) {
if (m_cookies.contains(oldCookie)) {
m_cookies.erase(oldCookie);
}
cookie.setMaxAge(std::chrono::seconds(0));
cookie.setValue("");
} else {
auto newToken = result.newToken();
if (!newToken.empty()) {
if (m_cookies.contains(oldCookie)) { // 勾选了记住我
m_cookies.erase(oldCookie);
cookie.setMaxAge(std::chrono::seconds(result.newTokenValidity()));
m_cookies.insert(newToken);
} else { // 只在会话期间有效
cookie.setExpires(Wt::WDateTime());
}
cookie.setValue(newToken);
}
}
return cookie;
}
} // namespace WebToolkit } // namespace WebToolkit

View File

@ -4,6 +4,7 @@
#include "Singleton.h" #include "Singleton.h"
#include <Wt/WApplication.h> #include <Wt/WApplication.h>
#include <memory> #include <memory>
#include <unordered_set>
namespace Wt { namespace Wt {
class WServer; class WServer;
@ -13,6 +14,7 @@ class WEnvironment;
namespace Auth { namespace Auth {
class AuthService; class AuthService;
class PasswordService; class PasswordService;
class AuthTokenResult;
} // namespace Auth } // namespace Auth
}; // namespace Wt }; // namespace Wt
@ -51,6 +53,8 @@ public:
void initializeAuthenticationService(); void initializeAuthenticationService();
Wt::Auth::AuthService &authService(); Wt::Auth::AuthService &authService();
const Wt::Auth::PasswordService &passwordService(); const Wt::Auth::PasswordService &passwordService();
void insertCookie(const std::string &cookie);
Wt::Http::Cookie updateCookie(const std::string &oldCookie, const Wt::Auth::AuthTokenResult &result, bool secure);
protected: protected:
Server(uint16_t port, const std::string &applicationRoot, const std::string &documentRoot); Server(uint16_t port, const std::string &applicationRoot, const std::string &documentRoot);
@ -61,6 +65,8 @@ private:
std::unique_ptr<Wt::Auth::AuthService> m_authService; std::unique_ptr<Wt::Auth::AuthService> m_authService;
std::unique_ptr<Wt::Auth::PasswordService> m_passwordService; std::unique_ptr<Wt::Auth::PasswordService> m_passwordService;
std::unordered_set<std::string> m_cookies;
}; };
} // namespace WebToolkit } // namespace WebToolkit
#endif // __WEBAPPLICATION_H__ #endif // __WEBAPPLICATION_H__

View File

@ -7,9 +7,10 @@ add_library(WebApplication
LoginPage.h LoginPage.cpp LoginPage.h LoginPage.cpp
NavigationBar.h NavigationBar.cpp NavigationBar.h NavigationBar.cpp
VisitorRecordsPage.h VisitorRecordsPage.cpp VisitorRecordsPage.h VisitorRecordsPage.cpp
VisitorRecordTableModel.h VisitorRecordTableModel.cpp
Restful.h Restful.cpp Restful.h Restful.cpp
Dialog.h Dialog.cpp Dialog.h Dialog.cpp
model/AuthModel.h model/AuthModel.cpp
model/VisitorRecordTableModel.h model/VisitorRecordTableModel.cpp
) )
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)

View File

@ -1,5 +1,6 @@
#include "LoginPage.h" #include "LoginPage.h"
#include "Application.h" #include "Application.h"
#include "model/AuthModel.h"
#include <Wt/Auth/AuthService.h> #include <Wt/Auth/AuthService.h>
#include <Wt/Auth/PasswordService.h> #include <Wt/Auth/PasswordService.h>
#include <Wt/WEnvironment.h> #include <Wt/WEnvironment.h>
@ -7,6 +8,7 @@
LoginPage::LoginPage(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUserDatabase &users, Wt::Auth::Login &login) LoginPage::LoginPage(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUserDatabase &users, Wt::Auth::Login &login)
: Wt::Auth::AuthWidget(baseAuth, users, login) { : Wt::Auth::AuthWidget(baseAuth, users, login) {
setModel(std::make_unique<AuthModel>(baseAuth, users));
auto app = Amass::Singleton<WebToolkit::Server>::instance(); auto app = Amass::Singleton<WebToolkit::Server>::instance();
// setInternalBasePath("/wt"); // setInternalBasePath("/wt");
model()->addPasswordAuth(&app->passwordService()); model()->addPasswordAuth(&app->passwordService());

View File

@ -1,7 +1,7 @@
#include "VisitorRecordsPage.h" #include "VisitorRecordsPage.h"
#include "BoostLog.h" #include "BoostLog.h"
#include "Database/Session.h" #include "Database/Session.h"
#include "VisitorRecordTableModel.h" #include "model/VisitorRecordTableModel.h"
#include <Wt/Dbo/QueryModel.h> #include <Wt/Dbo/QueryModel.h>
#include <Wt/WBreak.h> #include <Wt/WBreak.h>
#include <Wt/WItemDelegate.h> #include <Wt/WItemDelegate.h>

View File

@ -0,0 +1,44 @@
#include "AuthModel.h"
#include "../Application.h"
#include <Wt/Http/Cookie.h>
#include <Wt/WApplication.h>
#include <Wt/WEnvironment.h>
AuthModel::AuthModel(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUserDatabase &users)
: Wt::Auth::AuthModel(baseAuth, users) {
}
Wt::Auth::User AuthModel::processAuthToken() {
using namespace Wt::Auth;
if (baseAuth()->authTokensEnabled()) {
Wt::WApplication *app = Wt::WApplication::instance();
const Wt::WEnvironment &env = app->environment();
const std::string *token = env.getCookie(baseAuth()->authTokenCookieName());
if (token) {
AuthTokenResult result = baseAuth()->processAuthToken(*token, users());
auto server = Amass::Singleton<WebToolkit::Server>::instance();
auto cookie = server->updateCookie(*token, result, app->environment().urlScheme() == "https");
if ((result.state() == AuthTokenState::Invalid) || !cookie.value().empty()) {
app->setCookie(cookie);
}
return result.state() == AuthTokenState::Valid ? result.user() : User();
}
}
return User();
}
void AuthModel::setRememberMeCookie(const Wt::Auth::User &user) {
using namespace Wt::Auth;
Wt::WApplication *app = Wt::WApplication::instance();
const AuthService *s = baseAuth();
Wt::Http::Cookie cookie(s->authTokenCookieName(), s->createAuthToken(user),
std::chrono::seconds(s->authTokenValidity() * 60));
cookie.setDomain(s->authTokenCookieDomain());
cookie.setPath(CookiePath);
cookie.setSecure(app->environment().urlScheme() == "https");
auto server = Amass::Singleton<WebToolkit::Server>::instance();
server->insertCookie(cookie.value());
app->setCookie(cookie);
}

View File

@ -0,0 +1,14 @@
#ifndef __AUTHMODEL_H__
#define __AUTHMODEL_H__
#include <Wt/Auth/AuthModel.h>
class AuthModel : public Wt::Auth::AuthModel {
public:
static constexpr auto CookiePath = "/";
AuthModel(const Wt::Auth::AuthService &baseAuth, Wt::Auth::AbstractUserDatabase &users);
Wt::Auth::User processAuthToken() final;
void setRememberMeCookie(const Wt::Auth::User &user) final;
};
#endif // __AUTHMODEL_H__