@@ -6,13 +6,17 @@ import (
6
6
"log"
7
7
"net/http"
8
8
"net/url"
9
+ "time"
9
10
)
10
11
11
12
// ReverseProxy 结构体,用于管理反向代理的目标服务器
12
13
type ReverseProxy struct {
13
14
Targets []* url.URL
14
15
Transport http.RoundTripper
15
16
current int
17
+ //新增部分
18
+ AuthCheckClient * http.Client // 权限管理模块的客户端
19
+ AuthCheckURL string // 权限管理模块的检查URL
16
20
}
17
21
18
22
// 选择目标服务器,轮询算法
@@ -22,46 +26,93 @@ func (rp *ReverseProxy) getNextTarget() *url.URL {
22
26
return target
23
27
}
24
28
29
+ // 创建了一个新的方法checkAuthorization,它会构造一个请求发送给权限管理模块,并根据其响应决定是否继续处理原始请求。
30
+ // 如果权限管理模块拒绝了请求或返回非成功的状态码,则返回错误。
31
+ // 检查权限
32
+ func (rp * ReverseProxy ) checkAuthorization (req * http.Request ) error {
33
+ userID := req .Header .Get ("X-User-ID" ) // 获取用户ID
34
+ if userID == "" { //并且如果用户ID缺失,则直接返回错误。这确保了权限管理模块有足够的信息来进行授权决策。
35
+ return fmt .Errorf ("missing user ID" )
36
+ }
37
+ // 创建一个新的请求发送到权限管理模块
38
+ authReq , err := http .NewRequest ("POST" , rp .AuthCheckURL , nil )
39
+ if err != nil {
40
+ return fmt .Errorf ("failed to create auth request: %v" , err )
41
+ }
42
+
43
+ // 将原始请求的相关信息添加到权限管理模块请求的头部或body中,例如用户ID、请求路径等
44
+ // 这里假设权限管理模块期望在header中找到这些信息
45
+ authReq .Header .Set ("X-Original-User" , userID ) //将用户ID添加到发送给权限管理模块的请求头部,以便权限管理模块可以根据用户信息进行权限检查。//新增部分,方便联动
46
+ authReq .Header .Set ("X-Original-Path" , req .URL .Path )
47
+ authReq .Header .Set ("X-Original-Method" , req .Method )
48
+ // 可以根据实际情况添加更多需要传递的信息
49
+
50
+ // 发送请求到权限管理模块
51
+ resp , err := rp .AuthCheckClient .Do (authReq )
52
+ if err != nil {
53
+ return fmt .Errorf ("error contacting auth service: %v" , err )
54
+ }
55
+ defer resp .Body .Close ()
56
+
57
+ // 检查权限管理模块的响应状态码
58
+ if resp .StatusCode != http .StatusOK {
59
+ body , _ := io .ReadAll (resp .Body ) // 读取响应体以便记录更多错误信息
60
+ return fmt .Errorf ("auth service denied the request with status code: %d, response: %s" , resp .StatusCode , string (body )) //在权限检查失败时,不仅检查状态码,还读取权限管理模块的响应体,并将其包含在错误信息中。这有助于更详细地了解权限拒绝的原因,便于调试和问题排查。
61
+ }
62
+
63
+ return nil
64
+ }
65
+
25
66
// ServeHTTP 方法,用于处理请求并将其转发到目标服务器
26
67
func (rp * ReverseProxy ) ServeHTTP (w http.ResponseWriter , req * http.Request ) {
27
- // 选择目标服务器
28
- target := rp .getNextTarget ()
68
+ // 检查权限
69
+ if err := rp .checkAuthorization (req ); err != nil {
70
+ log .Printf ("Authorization check failed: %v" , err )
71
+ http .Error (w , "Forbidden." , http .StatusForbidden )
72
+ return
73
+ }
29
74
30
- // 修改请求的 URL,将请求重定向到目标服务器
75
+ // 如果权限检查通过,则继续处理请求
76
+ target := rp .getNextTarget ()
31
77
req .URL .Scheme = target .Scheme
32
78
req .URL .Host = target .Host
33
79
req .RequestURI = "" // 去掉原始请求的 URI
34
80
35
- // 使用指定的 Transport 来发送请求到后端服务器
36
81
resp , err := rp .Transport .RoundTrip (req )
37
82
if err != nil {
38
- // 错误处理
39
83
log .Printf ("Error contacting backend %s: %v" , target .Host , err )
40
84
http .Error (w , fmt .Sprintf ("Error contacting backend: %v" , err ), http .StatusInternalServerError )
41
85
return
42
86
}
43
87
defer resp .Body .Close ()
44
88
45
- // 将后端服务器的响应复制到客户端
46
89
for key , value := range resp .Header {
47
90
w .Header ()[key ] = value
48
91
}
49
92
w .WriteHeader (resp .StatusCode )
50
93
io .Copy (w , resp .Body )
51
94
}
52
95
53
- // main 函数,设置反向代理并启动 HTTP 服务器
54
96
func main () {
55
97
// 配置多个后端服务器
56
98
targetURLs := []* url.URL {
57
- // 请替换成你实际的目标服务器地址
58
99
& url.URL {Scheme : "http" , Host : "127.0.0.1:8081" },
59
100
}
60
101
102
+ // 权限管理模块的URL和HTTP客户端配置
103
+ //根据github库里面负责权限管理同学写的代码 权限检查的API端点是在http://auth-service:8001/verify
104
+ authCheckURL := "http://auth-service:8001/verify" // 更新为权限管理模块的实际地址
105
+ authCheckClient := & http.Client {
106
+ Timeout : 5 * time .Second , // 设置5秒的超时时间
107
+ }
108
+ // 创建带有超时设置的HTTP客户端
109
+
61
110
// 创建一个反向代理实例
62
111
proxy := & ReverseProxy {
63
- Targets : targetURLs ,
64
- Transport : http .DefaultTransport ,
112
+ Targets : targetURLs ,
113
+ Transport : http .DefaultTransport ,
114
+ AuthCheckClient : authCheckClient ,
115
+ AuthCheckURL : authCheckURL ,
65
116
}
66
117
67
118
// 设置 HTTP 路由,所有请求都交给反向代理处理
0 commit comments