Skip to content

Commit 9c9cd5f

Browse files
committed
docs(i18n): middleware (zh-cn, ja)
1 parent 3a39423 commit 9c9cd5f

50 files changed

Lines changed: 5606 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
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: ユーザー名とパスワードの認証情報を検証する HTTP Basic 認証ミドルウェアです。
4+
sidebar:
5+
order: 1
6+
---
7+
8+
Basic Auth ミドルウェアは HTTP Basic 認証を提供します。
9+
10+
- 有効な認証情報の場合、次のハンドラを呼び出します。
11+
- 認証情報がない、または無効な場合は `401 Unauthorized` レスポンスを送信します。
12+
13+
## 使い方
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+
## カスタム設定
27+
28+
```go
29+
e.Use(middleware.BasicAuthWithConfig(middleware.BasicAuthConfig{}))
30+
```
31+
32+
## 設定
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` のシグネチャは次のとおりです。
57+
58+
```go
59+
type BasicAuthValidator func(c *echo.Context, user string, password string) (bool, error)
60+
```
61+
62+
### デフォルト設定
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[セキュリティ]
73+
タイミング攻撃を防ぐため、認証情報の比較には必ず `subtle.ConstantTimeCompare` を使ってください。
74+
:::
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: ボディダンプ
3+
description: リクエストとレスポンスのペイロードをキャプチャし、ログ記録やデバッグ用のハンドラへ渡します。
4+
sidebar:
5+
order: 2
6+
---
7+
8+
Body Dump ミドルウェアは、リクエストとレスポンスのペイロードをキャプチャして登録済みハンドラへ渡します。
9+
一般的にはデバッグやログ記録に使います。
10+
11+
:::caution
12+
ファイルのアップロードやダウンロードなど、大きなペイロードには Body Dump を避けてください。
13+
そのようなルートで使う必要がある場合は、skipper 関数に例外を追加してください。
14+
:::
15+
16+
## 使い方
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+
## カスタム設定
26+
27+
```go
28+
e := echo.New()
29+
e.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{}))
30+
```
31+
32+
## 設定
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` のシグネチャは次のとおりです。
58+
59+
```go
60+
type BodyDumpHandler func(c *echo.Context, reqBody []byte, resBody []byte, err error)
61+
```
62+
63+
### デフォルト設定
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: ボディ制限
3+
description: ボディが設定済みの最大サイズを超えるリクエストを拒否します。
4+
sidebar:
5+
order: 3
6+
---
7+
8+
Body Limit ミドルウェアはリクエストボディに許可される最大サイズを設定します。
9+
サイズが設定値を超えた場合、`413 Request Entity Too Large` レスポンスを送信します。
10+
11+
この制限は `Content-Length` リクエスト header と実際に読み取られた内容の両方に適用されるため、
12+
偽装された header に対しても耐性があります。制限値はバイト単位で指定します。
13+
14+
## 使い方
15+
16+
```go
17+
e := echo.New()
18+
e.Use(middleware.BodyLimit(2_097_152)) // 2 MB
19+
```
20+
21+
## カスタム設定
22+
23+
```go
24+
e := echo.New()
25+
e.Use(middleware.BodyLimitWithConfig(middleware.BodyLimitConfig{}))
26+
```
27+
28+
## 設定
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+
### デフォルト設定
41+
42+
```go
43+
// Effective defaults applied when fields are left unset (Limit is required).
44+
BodyLimitConfig{
45+
Skipper: DefaultSkipper,
46+
}
47+
```
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
title: Casbin 認可
3+
description: 小さなカスタムミドルウェアで Casbin アクセス制御ライブラリを使い、リクエストを認可します。
4+
sidebar:
5+
order: 4
6+
---
7+
8+
[Casbin](https://github.com/casbin/casbin) は、Go 向けの強力で効率的なオープンソース
9+
アクセス制御ライブラリです。多くのモデルで認可を強制できます。
10+
11+
- ACL(Access Control List)
12+
- スーパーユーザー付き ACL
13+
- ユーザーなし ACL:認証やユーザーログインがないシステムに有用
14+
- リソースなし ACL:個別リソースではなく、リソース種別(例:`write-article``read-log`)を対象にする
15+
- RBAC(Role-Based Access Control)
16+
- リソースロール付き RBAC:ユーザーとリソースの両方がロールを持てる
17+
- ドメイン/テナント付き RBAC:ユーザーがドメイン/テナントごとに異なるロールセットを持てる
18+
- ABAC(Attribute-Based Access Control)
19+
- RESTful
20+
- Deny-override:allow と deny の両方のルールをサポートし、deny が allow を上書きする
21+
22+
詳細は [API overview](https://casbin.org/docs/api-overview)
23+
[Casbin documentation](https://casbin.org/docs/) を参照してください。
24+
25+
## 依存関係
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+
## 実装
38+
39+
Echo には Casbin ミドルウェアは同梱されていません。この連携は Casbin enforcer の小さなラッパーです。
40+
41+
```go
42+
// NewCasbinMiddleware returns middleware for Casbin (https://casbin.org/).
43+
func NewCasbinMiddleware(enforcer *casbin.Enforcer, userGetter func(*echo.Context) (string, error)) echo.MiddlewareFunc {
44+
return func(next echo.HandlerFunc) echo.HandlerFunc {
45+
return func(c *echo.Context) error {
46+
username, err := userGetter(c)
47+
if err != nil {
48+
return echo.ErrUnauthorized.Wrap(err)
49+
}
50+
if pass, err := enforcer.Enforce(username, c.Request().URL.Path, c.Request().Method); err != nil {
51+
return echo.ErrInternalServerError.Wrap(err)
52+
} else if !pass {
53+
return echo.NewHTTPError(http.StatusForbidden, "access denied")
54+
}
55+
return next(c)
56+
}
57+
}
58+
}
59+
```
60+
61+
##
62+
63+
Casbin モデルファイル `auth_model.conf` を作成します。
64+
65+
```ini
66+
[request_definition]
67+
r = sub, obj, act
68+
69+
[policy_definition]
70+
p = sub, obj, act
71+
72+
[role_definition]
73+
g = _, _
74+
75+
[policy_effect]
76+
e = some(where (p.eft == allow))
77+
78+
[matchers]
79+
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")
80+
```
81+
82+
Casbin ポリシーファイル `auth_policy.csv` を作成します。
83+
84+
```csv
85+
p, 1234567890, /dataset1/*, GET
86+
p, alice, /dataset1/*, GET
87+
p, alice, /dataset1/resource1, POST
88+
p, bob, /dataset2/resource1, *
89+
p, bob, /dataset2/resource2, GET
90+
p, bob, /dataset2/folder1/*, POST
91+
p, dataset1_admin, /dataset1/*, *
92+
g, cathy, dataset1_admin
93+
```
94+
95+
認証と認可は別の関心事です。JWT や Basic Auth など別のミドルウェアでユーザーを認証し、
96+
Casbin がリクエストを認可できるよう `userGetter` を渡します。
97+
98+
### JWT と使う
99+
100+
```go
101+
e.Use(echojwt.JWT([]byte("secret"))) // JWT middleware does authentication
102+
jwtUser := func(c *echo.Context) (string, error) { // JWT user getter for Casbin authorization
103+
token, err := echo.ContextGet[*jwt.Token](c, "user")
104+
if err != nil {
105+
return "", err
106+
}
107+
return token.Claims.GetSubject()
108+
}
109+
e.Use(NewCasbinMiddleware(ce, jwtUser)) // Casbin does authorization
110+
```
111+
112+
次で試します。
113+
114+
```bash
115+
curl -v "http://localhost:8080/dataset1/any" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
116+
```
117+
118+
### Basic Auth と使う
119+
120+
```go
121+
// BasicAuth middleware does authentication
122+
e.Use(middleware.BasicAuth(func(c *echo.Context, user, password string) (bool, error) {
123+
return subtle.ConstantTimeCompare([]byte(user), []byte("alice")) == 1 &&
124+
subtle.ConstantTimeCompare([]byte(password), []byte("password")) == 1, nil
125+
}))
126+
basicAuthUser := func(c *echo.Context) (string, error) { // Basic auth user getter for Casbin authorization
127+
username, _, _ := c.Request().BasicAuth() // password is verified by the BasicAuth middleware above
128+
return username, nil
129+
}
130+
e.Use(NewCasbinMiddleware(ce, basicAuthUser)) // Casbin does authorization
131+
```
132+
133+
次で試します。
134+
135+
```bash
136+
# should pass
137+
curl -v -u "alice:password" http://localhost:8080/dataset1/any
138+
# should fail
139+
curl -v -u "alice:password" http://localhost:8080/dataset2/resource2
140+
```
141+
142+
### Casbin + JWT の完全な例
143+
144+
```go
145+
package main
146+
147+
import (
148+
"log/slog"
149+
"net/http"
150+
151+
"github.com/casbin/casbin/v3"
152+
"github.com/golang-jwt/jwt/v5"
153+
echojwt "github.com/labstack/echo-jwt/v5"
154+
"github.com/labstack/echo/v5"
155+
)
156+
157+
// NewCasbinMiddleware returns middleware for Casbin (https://casbin.org/).
158+
func NewCasbinMiddleware(enforcer *casbin.Enforcer, userGetter func(*echo.Context) (string, error)) echo.MiddlewareFunc {
159+
return func(next echo.HandlerFunc) echo.HandlerFunc {
160+
return func(c *echo.Context) error {
161+
username, err := userGetter(c)
162+
if err != nil {
163+
return echo.ErrUnauthorized.Wrap(err)
164+
}
165+
if pass, err := enforcer.Enforce(username, c.Request().URL.Path, c.Request().Method); err != nil {
166+
return echo.ErrInternalServerError.Wrap(err)
167+
} else if !pass {
168+
return echo.NewHTTPError(http.StatusForbidden, "access denied")
169+
}
170+
return next(c)
171+
}
172+
}
173+
}
174+
175+
func main() {
176+
e := echo.New()
177+
178+
ce, err := casbin.NewEnforcer("auth_model.conf", "auth_policy.csv")
179+
if err != nil {
180+
slog.Error("failed to initialize Casbin enforcer", "error", err)
181+
}
182+
183+
e.Use(echojwt.JWT([]byte("secret"))) // JWT middleware does authentication
184+
jwtUser := func(c *echo.Context) (string, error) { // JWT user getter for Casbin authorization
185+
token, err := echo.ContextGet[*jwt.Token](c, "user")
186+
if err != nil {
187+
return "", err
188+
}
189+
return token.Claims.GetSubject()
190+
}
191+
e.Use(NewCasbinMiddleware(ce, jwtUser)) // Casbin does authorization
192+
193+
e.GET("/*", func(c *echo.Context) error {
194+
return c.String(http.StatusOK, "Hello, World!")
195+
})
196+
197+
if err := e.Start(":8080"); err != nil {
198+
e.Logger.Error("failed to start server", "error", err)
199+
}
200+
}
201+
```

0 commit comments

Comments
 (0)