eQuantic.UIeQuantic.UI
Docs
Playground
GitHub
DocsServidor
Seguridad y Server Actions
Edit this page
4 min read
eQuantic.UI facilita la comunicación entre el cliente y el servidor a través de Server Actions, asegurando al mismo tiempo que ese puente sea seguro por defecto.
⚡ Server Actions
Una Server Action es un método C# definido en un componente que se puede invocar directamente desde el navegador. El compilador genera automáticamente el puente de llamada (Fetch API) y el middleware del servidor resuelve la ejecución.
Ejemplo:
1
2
3
4
5
[ServerAction]
[Authorize(Roles = "Admin")]
public async Task<bool> DeleteUser(Guid userId) {
// Lógica ejecutada solo en el servidor
}
🔒 Una página que exige autorización
Desde 0.2.0-preview.61
1
2
3
[Page("/backoffice/queue")]
[Authorize(Policy = "Backoffice")]
public sealed class VerificationQueuePage : StatefulComponent, IServerPrefetch { … }
Los mismos [Authorize] y [AllowAnonymous] que toma una Server Action guardan una página. Su ruta los lleva como metadatos de endpoint, como lo haría RequireAuthorization, así que la autorización de ASP.NET Core decide con los esquemas y las políticas que la aplicación configuró (AddAuthentication, AddAuthorization):
•
una carga completa anónima es desafiada por el esquema por defecto, la redirección de OpenID Connect para iniciar sesión, por ejemplo;
•
quien ha iniciado sesión sin la política recibe un 403;
•
una navegación de cliente hacia la página recibe un 401 o un 403 en lugar de la página, y el router entonces carga la ruta por completo, así que el desafío o el 403 ocurre como ocurriría en cualquier visita;
•
una petición rechazada nunca llega a la página: su IServerPrefetch no corre, y ninguno de sus campos se escribe en el HTML.
[Authorize] sin política pide solo que haya sesión iniciada. Bajo una FallbackPolicy para toda la aplicación, una página marcada [AllowAnonymous] (la página de inicio de sesión) sigue sirviéndose, y también el runtime y los módulos de página que necesita. Un [Authorize] a nivel de clase guardaba solo las Server Actions de la página; ahora guarda también la página.
A las páginas 404 y 500 que registra una aplicación se les hace la misma pregunta antes de dibujarlas en lugar de una ruta, igual que la hacen sus propias rutas: una página que no nombra requisito alguno está bajo la FallbackPolicy, la petición es el recurso de la política, y una página que quien visita no puede ver no se dibuja, ni corre su IServerPrefetch.
🛡️ Capas de protección
1. Autorización (RBAC)
eQuantic.UI soporta los atributos [Authorize] y [AllowAnonymous].
•
El ServerActionsMiddleware comprueba si el usuario actual tiene los permisos necesarios antes de invocar el método.
•
Si la autorización falla, el servidor devuelve un error 403 Forbidden o 401 Unauthorized, bloqueando la ejecución de la lógica de negocio.
2. Validación del payload
Para prevenir ataques de inyección y el consumo excesivo de recursos:
•
Límite de tamaño: el middleware impone límites estrictos al tamaño del cuerpo de la petición.
•
Lista blanca de tipos: la deserialización de argumentos está restringida a tipos conocidos y seguros, lo que previene los ataques de deserialización insegura.
3. Registro de acciones
Solo se pueden invocar los métodos marcados explícitamente con [ServerAction]. No es posible llamar a cualquier método público arbitrario vía API, lo que asegura que la superficie de ataque esté controlada.
4. De dónde vino la petición
Desde 0.2.0-preview.61
Una Server Action rechaza una petición que envía la página de otro sitio, antes de leer nada de ella. El navegador dice de dónde vino una petición, y el endpoint responde 403 Forbidden cuando:
•
el Origin no es ni el host propio de la aplicación ni un origen que la aplicación permita, el Origin: null opaco incluido;
•
no hay Origin, y Sec-Fetch-Site dice cross-site o same-site.
Una petición sin ninguna de las dos cabeceras no es de un navegador, y corre. El host propio de la aplicación es el Host de la petición: detrás de un proxy que lo reescribe, app.UseForwardedHeaders() lo restaura a partir de los proxies en los que la aplicación confía, y un X-Forwarded-Host en crudo nunca se lee. Se comparan el host y el puerto, no el esquema, y un Host sin puerto representa el puerto por defecto del origen, así que una aplicación detrás de un proxy que termina TLS no necesita ningún ajuste.
Una página servida desde otro dominio que sus acciones lista ese origen, en appsettings.json:
1
2
3
4
5
6
7
{
"EQuantic": {
"ServerActions": {
"AllowedOrigins": [ "https://admin.example.com" ]
}
}
}
o en Program.cs:
1
builder.Services.AddUI(options => options.AllowServerActionOrigins("https://admin.example.com"));
Cada origen es scheme://host[:port], sin ruta ni query. Uno que no lo sea detiene la aplicación al arrancar, nombrando el valor.
📡 Protocolo de comunicación
La comunicación se hace vía HTTP POST al endpoint reservado /api/_equantic/actions.
•
Payload: contiene el ID único de la Action y la lista de argumentos serializados.
•
Respuesta: devuelve el objeto resultado o un error estructurado.