Skip to content

Commit 1c52f4b

Browse files
committed
docs(i18n): middleware (es)
1 parent 34ea72a commit 1c52f4b

25 files changed

Lines changed: 2827 additions & 0 deletions
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
title: Basic Auth
3+
description: Middleware de autenticación HTTP Basic que valida credenciales de username y password.
4+
sidebar:
5+
order: 1
6+
---
7+
8+
El middleware Basic Auth proporciona autenticación HTTP basic.
9+
10+
- Para credenciales válidas llama al siguiente handler.
11+
- Para credenciales ausentes o inválidas, envía una response `401 Unauthorized`.
12+
13+
## Uso
14+
15+
```go
16+
e.Use(middleware.BasicAuth(func(c *echo.Context, username, password string) (bool, error) {
17+
// Use a constant time comparison to prevent timing attacks.
18+
if subtle.ConstantTimeCompare([]byte(username), []byte("joe")) == 1 &&
19+
subtle.ConstantTimeCompare([]byte(password), []byte("secret")) == 1 {
20+
return true, nil
21+
}
22+
return false, nil
23+
}))
24+
```
25+
26+
## Configuración personalizada
27+
28+
```go
29+
e.Use(middleware.BasicAuthWithConfig(middleware.BasicAuthConfig{}))
30+
```
31+
32+
## Configuración
33+
34+
```go
35+
type BasicAuthConfig struct {
36+
// Skipper defines a function to skip middleware.
37+
Skipper Skipper
38+
39+
// Validator validates the credentials. If the request contains multiple basic
40+
// auth headers, it is called once for each header until the first valid result.
41+
// Required.
42+
Validator BasicAuthValidator
43+
44+
// Realm is the realm attribute of the WWW-Authenticate header.
45+
// Default value "Restricted".
46+
Realm string
47+
48+
// AllowedCheckLimit sets how many headers are allowed to be checked. This is
49+
// useful in environments such as corporate test setups with application proxies
50+
// restricting access with their own auth scheme.
51+
// Default value 1.
52+
AllowedCheckLimit uint
53+
}
54+
```
55+
56+
`Validator` tiene esta firma:
57+
58+
```go
59+
type BasicAuthValidator func(c *echo.Context, user string, password string) (bool, error)
60+
```
61+
62+
### Configuración por defecto
63+
64+
```go
65+
// Effective defaults applied when fields are left unset.
66+
BasicAuthConfig{
67+
Skipper: DefaultSkipper,
68+
Realm: "Restricted",
69+
}
70+
```
71+
72+
:::caution[Seguridad]
73+
Compara siempre las credenciales con `subtle.ConstantTimeCompare` para prevenir timing attacks.
74+
:::
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: Body Dump
3+
description: Captura payloads de request y response y pásalos a un handler para logging o debugging.
4+
sidebar:
5+
order: 2
6+
---
7+
8+
El middleware Body Dump captura los payloads de request y response y los pasa a un
9+
handler registrado. Generalmente se usa para debugging o logging.
10+
11+
:::caution
12+
Evita Body Dump para payloads grandes, como uploads o downloads de archivos. Si debes usarlo
13+
en esas rutas, agrega una excepción en la función skipper.
14+
:::
15+
16+
## Uso
17+
18+
```go
19+
e := echo.New()
20+
e.Use(middleware.BodyDump(func(c *echo.Context, reqBody, resBody []byte, err error) {
21+
// Handle the request and response bodies.
22+
}))
23+
```
24+
25+
## Configuración personalizada
26+
27+
```go
28+
e := echo.New()
29+
e.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{}))
30+
```
31+
32+
## Configuración
33+
34+
```go
35+
type BodyDumpConfig struct {
36+
// Skipper defines a function to skip middleware.
37+
Skipper Skipper
38+
39+
// Handler receives the request and response payloads and the handler error, if any.
40+
// Required.
41+
Handler BodyDumpHandler
42+
43+
// MaxRequestBytes limits how much of the request body to dump. If the request body
44+
// exceeds this limit, only the first MaxRequestBytes are dumped and the handler
45+
// receives truncated data.
46+
// Default: 5 * MB (5,242,880 bytes). Set to -1 to disable limits (not recommended).
47+
MaxRequestBytes int64
48+
49+
// MaxResponseBytes limits how much of the response body to dump. If the response body
50+
// exceeds this limit, only the first MaxResponseBytes are dumped and the handler
51+
// receives truncated data.
52+
// Default: 5 * MB (5,242,880 bytes). Set to -1 to disable limits (not recommended).
53+
MaxResponseBytes int64
54+
}
55+
```
56+
57+
`Handler` tiene esta firma:
58+
59+
```go
60+
type BodyDumpHandler func(c *echo.Context, reqBody []byte, resBody []byte, err error)
61+
```
62+
63+
### Configuración por defecto
64+
65+
```go
66+
// Effective defaults applied when fields are left unset (Handler is required).
67+
BodyDumpConfig{
68+
Skipper: DefaultSkipper,
69+
MaxRequestBytes: 5 * MB,
70+
MaxResponseBytes: 5 * MB,
71+
}
72+
```
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: Body Limit
3+
description: Rechaza requests cuyo body supera un tamaño máximo configurado.
4+
sidebar:
5+
order: 3
6+
---
7+
8+
El middleware Body Limit establece el tamaño máximo permitido para un body de request. Si el tamaño
9+
supera el límite configurado, envía una response `413 Request Entity Too Large`.
10+
11+
El límite se aplica tanto al header de request `Content-Length` como al contenido real leído,
12+
lo que lo hace resistente a headers falsificados. El límite se especifica en bytes.
13+
14+
## Uso
15+
16+
```go
17+
e := echo.New()
18+
e.Use(middleware.BodyLimit(2_097_152)) // 2 MB
19+
```
20+
21+
## Configuración personalizada
22+
23+
```go
24+
e := echo.New()
25+
e.Use(middleware.BodyLimitWithConfig(middleware.BodyLimitConfig{}))
26+
```
27+
28+
## Configuración
29+
30+
```go
31+
type BodyLimitConfig struct {
32+
// Skipper defines a function to skip middleware.
33+
Skipper Skipper
34+
35+
// LimitBytes is the maximum allowed size in bytes for a request body.
36+
LimitBytes int64
37+
}
38+
```
39+
40+
### Configuración por defecto
41+
42+
```go
43+
// Effective defaults applied when fields are left unset (Limit is required).
44+
BodyLimitConfig{
45+
Skipper: DefaultSkipper,
46+
}
47+
```
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
---
2+
title: Casbin Auth
3+
description: Autoriza requests con la biblioteca de control de acceso Casbin usando un middleware personalizado pequeño.
4+
sidebar:
5+
order: 4
6+
---
7+
8+
[Casbin](https://github.com/casbin/casbin) es una biblioteca de control de acceso open-source
9+
potente y eficiente para Go. Soporta aplicar autorización en muchos modelos:
10+
11+
- ACL (Access Control List)
12+
- ACL con superuser
13+
- ACL sin usuarios, útil para sistemas sin autenticación o log-ins de usuario
14+
- ACL sin recursos: apunta a un tipo de recurso (por ejemplo `write-article`, `read-log`) en lugar de a uno individual
15+
- RBAC (Role-Based Access Control)
16+
- RBAC con roles de recursos: tanto usuarios como recursos pueden tener roles
17+
- RBAC con dominios/tenants: los usuarios pueden tener conjuntos de roles distintos por dominio/tenant
18+
- ABAC (Attribute-Based Access Control)
19+
- RESTful
20+
- Deny-override: se soportan reglas allow y deny; deny sobrescribe allow
21+
22+
Consulta el [resumen de API](https://casbin.org/docs/api-overview) y la
23+
[documentación de Casbin](https://casbin.org/docs/) para más detalles.
24+
25+
## Dependencias
26+
27+
```bash
28+
go get github.com/casbin/casbin/v3
29+
```
30+
31+
```go
32+
import (
33+
"github.com/casbin/casbin/v3"
34+
)
35+
```
36+
37+
## Implementación
38+
39+
Echo no incluye un middleware Casbin; la integración es un wrapper pequeño alrededor del
40+
enforcer de Casbin:
41+
42+
```go
43+
// NewCasbinMiddleware returns middleware for Casbin (https://casbin.org/).
44+
func NewCasbinMiddleware(enforcer *casbin.Enforcer, userGetter func(*echo.Context) (string, error)) echo.MiddlewareFunc {
45+
return func(next echo.HandlerFunc) echo.HandlerFunc {
46+
return func(c *echo.Context) error {
47+
username, err := userGetter(c)
48+
if err != nil {
49+
return echo.ErrUnauthorized.Wrap(err)
50+
}
51+
if pass, err := enforcer.Enforce(username, c.Request().URL.Path, c.Request().Method); err != nil {
52+
return echo.ErrInternalServerError.Wrap(err)
53+
} else if !pass {
54+
return echo.NewHTTPError(http.StatusForbidden, "access denied")
55+
}
56+
return next(c)
57+
}
58+
}
59+
}
60+
```
61+
62+
## Ejemplo
63+
64+
Crea un archivo de modelo Casbin `auth_model.conf`:
65+
66+
```ini
67+
[request_definition]
68+
r = sub, obj, act
69+
70+
[policy_definition]
71+
p = sub, obj, act
72+
73+
[role_definition]
74+
g = _, _
75+
76+
[policy_effect]
77+
e = some(where (p.eft == allow))
78+
79+
[matchers]
80+
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
81+
```
82+
83+
Crea un archivo de policy Casbin `auth_policy.csv`:
84+
85+
```csv
86+
p, 1234567890, /dataset1/*, GET
87+
p, alice, /dataset1/*, GET
88+
p, alice, /dataset1/resource1, POST
89+
p, bob, /dataset2/resource1, *
90+
p, bob, /dataset2/resource2, GET
91+
p, bob, /dataset2/folder1/*, POST
92+
p, dataset1_admin, /dataset1/*, *
93+
g, cathy, dataset1_admin
94+
```
95+
96+
La autenticación y la autorización son responsabilidades separadas. Autentica al usuario con
97+
otro middleware (como JWT o Basic Auth), y luego proporciona un `userGetter` para que Casbin
98+
pueda autorizar el request.
99+
100+
### Con JWT
101+
102+
```go
103+
e.Use(echojwt.JWT([]byte("secret"))) // JWT middleware does authentication
104+
jwtUser := func(c *echo.Context) (string, error) { // JWT user getter for Casbin authorization
105+
token, err := echo.ContextGet[*jwt.Token](c, "user")
106+
if err != nil {
107+
return "", err
108+
}
109+
return token.Claims.GetSubject()
110+
}
111+
e.Use(NewCasbinMiddleware(ce, jwtUser)) // Casbin does authorization
112+
```
113+
114+
Pruébalo con:
115+
116+
```bash
117+
curl -v "http://localhost:8080/dataset1/any" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
118+
```
119+
120+
### Con Basic Auth
121+
122+
```go
123+
// BasicAuth middleware does authentication
124+
e.Use(middleware.BasicAuth(func(c *echo.Context, user, password string) (bool, error) {
125+
return subtle.ConstantTimeCompare([]byte(user), []byte("alice")) == 1 &&
126+
subtle.ConstantTimeCompare([]byte(password), []byte("password")) == 1, nil
127+
}))
128+
basicAuthUser := func(c *echo.Context) (string, error) { // Basic auth user getter for Casbin authorization
129+
username, _, _ := c.Request().BasicAuth() // password is verified by the BasicAuth middleware above
130+
return username, nil
131+
}
132+
e.Use(NewCasbinMiddleware(ce, basicAuthUser)) // Casbin does authorization
133+
```
134+
135+
Pruébalo con:
136+
137+
```bash
138+
# should pass
139+
curl -v -u "alice:password" http://localhost:8080/dataset1/any
140+
# should fail
141+
curl -v -u "alice:password" http://localhost:8080/dataset2/resource2
142+
```
143+
144+
### Ejemplo completo de Casbin + JWT
145+
146+
```go
147+
package main
148+
149+
import (
150+
"log/slog"
151+
"net/http"
152+
153+
"github.com/casbin/casbin/v3"
154+
"github.com/golang-jwt/jwt/v5"
155+
echojwt "github.com/labstack/echo-jwt/v5"
156+
"github.com/labstack/echo/v5"
157+
)
158+
159+
// NewCasbinMiddleware returns middleware for Casbin (https://casbin.org/).
160+
func NewCasbinMiddleware(enforcer *casbin.Enforcer, userGetter func(*echo.Context) (string, error)) echo.MiddlewareFunc {
161+
return func(next echo.HandlerFunc) echo.HandlerFunc {
162+
return func(c *echo.Context) error {
163+
username, err := userGetter(c)
164+
if err != nil {
165+
return echo.ErrUnauthorized.Wrap(err)
166+
}
167+
if pass, err := enforcer.Enforce(username, c.Request().URL.Path, c.Request().Method); err != nil {
168+
return echo.ErrInternalServerError.Wrap(err)
169+
} else if !pass {
170+
return echo.NewHTTPError(http.StatusForbidden, "access denied")
171+
}
172+
return next(c)
173+
}
174+
}
175+
}
176+
177+
func main() {
178+
e := echo.New()
179+
180+
ce, err := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
181+
if err != nil {
182+
slog.Error("failed to initialize Casbin enforcer", "error", err)
183+
}
184+
185+
e.Use(echojwt.JWT([]byte("secret"))) // JWT middleware does authentication
186+
jwtUser := func(c *echo.Context) (string, error) { // JWT user getter for Casbin authorization
187+
token, err := echo.ContextGet[*jwt.Token](c, "user")
188+
if err != nil {
189+
return "", err
190+
}
191+
return token.Claims.GetSubject()
192+
}
193+
e.Use(NewCasbinMiddleware(ce, jwtUser)) // Casbin does authorization
194+
195+
e.GET("/*", func(c *echo.Context) error {
196+
return c.String(http.StatusOK, "Hello, World!")
197+
})
198+
199+
if err := e.Start(":8080"); err != nil {
200+
e.Logger.Error("failed to start server", "error", err)
201+
}
202+
}
203+
```

0 commit comments

Comments
 (0)