В Riot.js аутентификация реализуется через комбинацию управления состоянием приложения, компонентов и маршрутизации. Основной принцип заключается в хранении информации о пользователе и его сессии, проверке прав доступа и условной загрузке компонентов.
Для управления состоянием чаще всего используется объект
store или глобальный сервис, который хранит данные
пользователя:
import { observable } from 'riot';
export const authStore = observable({
user: null,
token: null,
login(userData, token) {
this.user = userData;
this.token = token;
localStorage.setItem('token', token);
},
logout() {
this.user = null;
this.token = null;
localStorage.removeItem('token');
},
isAuthenticated() {
return !!this.token;
}
});
Здесь authStore выполняет роль центра управления
аутентификацией. Метод isAuthenticated() позволяет
компонентам или маршрутам проверять состояние пользователя.
Riot.js использует собственный роутер, который позволяет задавать маршруты и условные проверки перед их отображением. Для защищённых маршрутов важно проверять наличие токена или авторизованного пользователя перед рендерингом компонента.
Пример конфигурации маршрутов с проверкой:
import { route } from 'riot';
import { authStore } from './authStore';
import Home from './components/Home.riot';
import Dashboard from './components/Dashboard.riot';
import Login from './components/Login.riot';
route('/', () => route('/home'));
route('/home', () => mount(Home));
route('/login', () => mount(Login));
route('/dashboard', () => {
if (authStore.isAuthenticated()) {
mount(Dashboard);
} else {
route('/login');
}
});
В этом примере путь /dashboard доступен только
авторизованному пользователю. Если проверка не проходит, происходит
перенаправление на страницу входа.
Компонент входа должен обрабатывать форму, отправлять данные на
сервер и обновлять состояние authStore после успешной
аутентификации:
<login>
<form onsub mit={handleLogin}>
<input type="text" placeholder="Email" ref="email">
<input type="password" placeholder="Password" ref="password">
<button type="submit">Войти</button>
</form>
<script>
import { authStore } from '../authStore';
import { route } from 'riot';
export default {
handleLogin(event) {
event.preventDefault();
const email = this.refs.email.value;
const password = this.refs.password.value;
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
})
.then(res => res.json())
.then(data => {
if (data.token) {
authStore.login(data.user, data.token);
route('/dashboard');
} else {
alert('Неверные данные');
}
});
}
}
</script>
</login>
Метод handleLogin обновляет глобальное состояние и
перенаправляет пользователя на защищённый маршрут после успешного
входа.
Токен обычно хранится в localStorage или
sessionStorage, что позволяет сохранять авторизацию между
перезагрузками страницы. Для более высокой безопасности следует
использовать HttpOnly cookie на сервере и проверять токен через API.
Пример проверки при загрузке приложения:
const token = localStorage.getItem('token');
if (token) {
fetch('/api/me', {
headers: { 'Authorization': `Bearer ${token}` }
})
.then(res => res.json())
.then(user => authStore.login(user, token))
.catch(() => authStore.logout());
}
Такой подход обеспечивает восстановление сессии при обновлении страницы и корректное состояние защищённых маршрутов.
Riot.js позволяет управлять видимостью элементов через условные рендеры. Это удобно для создания меню и интерфейсов, доступных только авторизованным пользователям:
<nav>
<ul>
<li if={!authStore.isAuthenticated()}><a href="/login">Вход</a></li>
<li if={authStore.isAuthenticated()}><a href="/dashboard">Панель</a></li>
<li if={authStore.isAuthenticated()}><button oncl ick={logout}>Выход</button></li>
</ul>
<script>
import { authStore } from '../authStore';
import { route } from 'riot';
export default {
logout() {
authStore.logout();
route('/home');
}
}
</script>
</nav>
Условные атрибуты if позволяют отображать или скрывать
элементы без перезагрузки страницы, основываясь на состоянии
authStore.
Для взаимодействия с сервером защищённые маршруты должны сопровождаться проверкой токена в заголовках запроса:
fetch('/api/protected', {
headers: { 'Authorization': `Bearer ${authStore.token}` }
})
.then(res => {
if (res.status === 401) {
authStore.logout();
route('/login');
}
return res.json();
})
.then(data => console.log(data));
Это предотвращает неавторизованный доступ и автоматически перенаправляет пользователя при истечении сессии.
Эта структура обеспечивает комплексную систему аутентификации и управления защищёнными маршрутами в приложении на Riot.js, сохраняя гибкость компонентов и централизованное управление состоянием.