Управление токенами — ключевой аспект безопасности клиентских веб-приложений. В контексте Mithril это особенно важно, так как фреймворк предоставляет лёгкую структуру для построения компонентов и маршрутизации, но не накладывает строгих ограничений на хранение и обработку данных аутентификации. Основные принципы заключаются в правильном хранении, обновлении и передаче токенов.
Существует несколько способов хранения токенов на клиенте:
LocalStorage Позволяет сохранять токен между сессиями. Основное преимущество — простота доступа из любого компонента. Недостаток — уязвимость к XSS-атакам, так как любой скрипт на странице может получить доступ к localStorage.
SessionStorage Данные живут только в рамках текущей вкладки браузера. Подходит для токенов, которые не должны сохраняться между сессиями. Более безопасно по сравнению с localStorage, но всё ещё подвержено XSS.
HTTP-only Cookies Токен сохраняется в cookie с
флагом HttpOnly, что делает его недоступным для JavaScript.
Этот способ наиболее безопасен против XSS, однако требует внимательного
контроля CSRF-атак.
Рекомендация: предпочтительно использовать HTTP-only cookies для хранения токенов с коротким сроком действия и периодическим обновлением.
Mithril предоставляет встроенный модуль m.request для
работы с HTTP-запросами. Токен передается в заголовках или как
cookie.
Пример передачи токена в заголовке Authorization:
m.request({
method: "GET",
url: "/api/user",
headers: {
"Authorization": `Bearer ${localStorage.getItem("authToken")}`
}
})
.then(response => {
console.log(response);
})
.catch(err => console.error(err));
Для cookie достаточно настроить сервер и включить опцию
withCredentials:
m.request({
method: "GET",
url: "/api/user",
withCredentials: true
})
Для токенов с ограниченным сроком жизни необходимо реализовать механизм refresh token. Он позволяет получать новый токен без повторного входа пользователя.
Структура работы:
access token) хранится в памяти или
sessionStorage.refresh token) хранится в HTTP-only
cookie./refresh для получения нового
токена.Пример логики в Mithril:
async function secureRequest(options) {
try {
return await m.request(options);
} catch (err) {
if (err.code === 401) {
// попытка обновления токена
await m.request({ method: "POST", url: "/refresh", withCredentials: true });
return m.request(options); // повторный запрос
}
throw err;
}
}
SameSite=Lax или Strict, чтобы предотвратить
несанкционированные запросы с других сайтов.Компоненты Mithril легко адаптируются для работы с токенами:
const UserProfile = {
oninit: vnode => {
secureRequest({ method: "GET", url: "/api/user", withCredentials: true })
.then(data => vnode.state.user = data);
},
view: vnode => m("div", vnode.state.user ? `Привет, ${vnode.state.user.name}` : "Загрузка...")
};
Использование централизованного запроса через
secureRequest позволяет автоматически обрабатывать истекшие
токены и повышает безопасность приложения без дублирования логики в
каждом компоненте.
Mithril Router позволяет защищать маршруты на основе наличия токена:
m.route(document.body, "/", {
"/": Home,
"/profile": {
onmatch: () => {
const token = sessionStorage.getItem("authToken");
return token ? UserProfile : m.route.set("/");
}
}
});
Такой подход предотвращает доступ к защищённым страницам без действительного токена и обеспечивает централизованное управление авторизацией.
secureRequest.Эти практики позволяют создавать безопасные и масштабируемые приложения на Mithril, минимизируя риски утечки и злоупотребления токенами.