Skip to content

Commit a3745c8

Browse files
CodeCasterXclaude
andcommitted
feat: Add comprehensive HTTP client authentication support
Implement @requestauth annotation with multi-level authentication support for HTTP client proxy interfaces. The new authentication system supports Bearer tokens, Basic auth, API keys, and custom authentication providers. Key Features: - @requestauth annotation with support for interface, method, and parameter levels - Multiple auth types: BEARER, BASIC, API_KEY, CUSTOM - Static configuration and dynamic AuthProvider support - Flexible parameter locations: HEADER, QUERY, COOKIE - Priority system: parameter > method > interface level - Seamless integration with existing Authorization system Implementation: - AuthType enum defining supported authentication types - AuthProvider interface for dynamic authentication - RequestAuthResolver for annotation parsing - AuthDestinationSetter for request building integration - StaticAuthApplier for class/method level static auth - Extended AnnotationParser to handle multi-level auth annotations Examples and Tests: - TestAuthClient demonstrating various auth scenarios - AuthProvider examples: DynamicTokenProvider, ApiKeyProvider, CustomSignatureProvider - Server-side TestAuthServerController for auth validation - Comprehensive unit tests for resolver and setter components - Updated TestClientController with auth testing endpoints 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 0e211d0 commit a3745c8

File tree

18 files changed

+1213
-2
lines changed

18 files changed

+1213
-2
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@
77

88
# Common
99
target/
10-
build/
10+
build/
11+
12+
# Claude Code local settings
13+
.claude/settings.local.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.example.auth;
8+
9+
import modelengine.fit.http.client.proxy.Authorization;
10+
import modelengine.fit.http.client.proxy.auth.AuthProvider;
11+
import modelengine.fit.http.server.handler.Source;
12+
import modelengine.fitframework.annotation.Component;
13+
14+
/**
15+
* API Key提供器示例。
16+
* 提供动态的API Key鉴权。
17+
*
18+
* @author 季聿阶
19+
* @since 2025-01-01
20+
*/
21+
@Component
22+
public class ApiKeyProvider implements AuthProvider {
23+
24+
@Override
25+
public Authorization provide() {
26+
// 模拟从配置或环境变量获取API Key
27+
String apiKey = "api-key-" + System.currentTimeMillis();
28+
return Authorization.createApiKey("X-API-Key", apiKey, Source.HEADER);
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.example.auth;
8+
9+
import modelengine.fit.http.client.proxy.Authorization;
10+
import modelengine.fit.http.client.proxy.RequestBuilder;
11+
import modelengine.fit.http.client.proxy.auth.AuthProvider;
12+
import modelengine.fitframework.annotation.Component;
13+
import modelengine.fitframework.util.StringUtils;
14+
15+
import java.nio.charset.StandardCharsets;
16+
import java.security.MessageDigest;
17+
import java.security.NoSuchAlgorithmException;
18+
19+
/**
20+
* 自定义签名鉴权提供器示例。
21+
* 演示如何实现复杂的自定义鉴权逻辑,如签名算法。
22+
*
23+
* @author 季聿阶
24+
* @since 2025-01-01
25+
*/
26+
@Component
27+
public class CustomSignatureProvider implements AuthProvider {
28+
29+
@Override
30+
public Authorization provide() {
31+
return new CustomSignatureAuthorization();
32+
}
33+
34+
/**
35+
* 自定义签名鉴权实现。
36+
* 在每次请求时生成时间戳和签名。
37+
*/
38+
private static class CustomSignatureAuthorization implements Authorization {
39+
private static final String SECRET_KEY = "my-secret-key";
40+
41+
@Override
42+
public void set(String key, Object value) {
43+
// 自定义鉴权不需要外部设置参数
44+
}
45+
46+
@Override
47+
public void assemble(RequestBuilder builder) {
48+
String timestamp = String.valueOf(System.currentTimeMillis());
49+
String signature = generateSignature(timestamp);
50+
51+
builder.header("X-Timestamp", timestamp);
52+
builder.header("X-Signature", signature);
53+
builder.header("X-App-Id", "fit-example-app");
54+
}
55+
56+
private String generateSignature(String timestamp) {
57+
try {
58+
String data = timestamp + SECRET_KEY;
59+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
60+
byte[] hash = digest.digest(data.getBytes(StandardCharsets.UTF_8));
61+
62+
// 简单的十六进制转换
63+
StringBuilder hexString = new StringBuilder();
64+
for (byte b : hash) {
65+
String hex = Integer.toHexString(0xff & b);
66+
if (hex.length() == 1) {
67+
hexString.append('0');
68+
}
69+
hexString.append(hex);
70+
}
71+
return hexString.toString();
72+
} catch (NoSuchAlgorithmException e) {
73+
throw new RuntimeException("Failed to generate signature", e);
74+
}
75+
}
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.example.auth;
8+
9+
import modelengine.fit.http.client.proxy.Authorization;
10+
import modelengine.fit.http.client.proxy.auth.AuthProvider;
11+
import modelengine.fitframework.annotation.Component;
12+
13+
/**
14+
* 动态Token提供器示例。
15+
* 模拟从某个Token管理器获取动态Token的场景。
16+
*
17+
* @author 季聿阶
18+
* @since 2025-01-01
19+
*/
20+
@Component
21+
public class DynamicTokenProvider implements AuthProvider {
22+
23+
@Override
24+
public Authorization provide() {
25+
// 模拟动态获取token
26+
String dynamicToken = "dynamic-token-" + System.currentTimeMillis();
27+
return Authorization.createBearer(dynamicToken);
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.example.client;
8+
9+
import modelengine.fit.example.auth.ApiKeyProvider;
10+
import modelengine.fit.example.auth.CustomSignatureProvider;
11+
import modelengine.fit.example.auth.DynamicTokenProvider;
12+
import modelengine.fit.http.annotation.GetMapping;
13+
import modelengine.fit.http.annotation.HttpProxy;
14+
import modelengine.fit.http.annotation.RequestAddress;
15+
import modelengine.fit.http.annotation.RequestAuth;
16+
import modelengine.fit.http.annotation.RequestMapping;
17+
import modelengine.fit.http.client.proxy.auth.AuthType;
18+
import modelengine.fit.http.server.handler.Source;
19+
20+
/**
21+
* 鉴权测试客户端实现。
22+
* 演示各种@RequestAuth注解的使用方式。
23+
*
24+
* @author 季聿阶
25+
* @since 2025-01-01
26+
*/
27+
@HttpProxy
28+
@RequestAddress(protocol = "http", host = "localhost", port = "8080")
29+
@RequestMapping(path = "/http-server/auth")
30+
// 接口级别的默认鉴权:API Key
31+
@RequestAuth(type = AuthType.API_KEY, name = "X-Service-Key", value = "service-default-key")
32+
public interface TestAuthClient extends TestAuthInterface {
33+
34+
@Override
35+
@GetMapping(path = "/bearer-static")
36+
// 方法级别覆盖:使用Bearer Token
37+
@RequestAuth(type = AuthType.BEARER, value = "static-bearer-token-12345")
38+
String testBearerStatic();
39+
40+
@Override
41+
@GetMapping(path = "/bearer-dynamic")
42+
// 方法级别覆盖:使用参数驱动的Bearer Token
43+
String testBearerDynamic(@RequestAuth(type = AuthType.BEARER) String token);
44+
45+
@Override
46+
@GetMapping(path = "/basic-static")
47+
// 方法级别覆盖:使用Basic Auth
48+
@RequestAuth(type = AuthType.BASIC, username = "admin", password = "secret123")
49+
String testBasicStatic();
50+
51+
@Override
52+
@GetMapping(path = "/apikey-header-static")
53+
// 方法级别覆盖:API Key在Header中
54+
@RequestAuth(type = AuthType.API_KEY, name = "X-API-Key", value = "static-api-key-67890")
55+
String testApiKeyHeaderStatic();
56+
57+
@Override
58+
@GetMapping(path = "/apikey-query-static")
59+
// 方法级别覆盖:API Key在Query参数中
60+
@RequestAuth(type = AuthType.API_KEY, name = "api_key", value = "query-api-key-111", location = Source.QUERY)
61+
String testApiKeyQueryStatic();
62+
63+
@Override
64+
@GetMapping(path = "/apikey-dynamic")
65+
// 参数驱动的API Key
66+
String testApiKeyDynamic(@RequestAuth(type = AuthType.API_KEY, name = "X-Dynamic-Key") String apiKey);
67+
68+
@Override
69+
@GetMapping(path = "/dynamic-provider")
70+
// 方法级别覆盖:使用动态Token Provider
71+
@RequestAuth(type = AuthType.BEARER, provider = DynamicTokenProvider.class)
72+
String testDynamicProvider();
73+
74+
@Override
75+
@GetMapping(path = "/custom-provider")
76+
// 方法级别覆盖:使用自定义签名Provider
77+
@RequestAuth(type = AuthType.CUSTOM, provider = CustomSignatureProvider.class)
78+
String testCustomProvider();
79+
80+
@Override
81+
@GetMapping(path = "/method-override")
82+
// 方法级别覆盖:使用API Key Provider
83+
@RequestAuth(type = AuthType.API_KEY, provider = ApiKeyProvider.class)
84+
String testMethodOverride();
85+
86+
@Override
87+
@GetMapping(path = "/combined-auth")
88+
// 组合鉴权:服务级API Key + 用户Token
89+
@RequestAuth(type = AuthType.BEARER, provider = DynamicTokenProvider.class)
90+
String testCombinedAuth(@RequestAuth(type = AuthType.API_KEY, name = "X-User-Context") String userToken);
91+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) 2025 Huawei Technologies Co., Ltd. All rights reserved.
3+
* This file is a part of the ModelEngine Project.
4+
* Licensed under the MIT License. See License.txt in the project root for license information.
5+
*--------------------------------------------------------------------------------------------*/
6+
7+
package modelengine.fit.example.client;
8+
9+
/**
10+
* 鉴权测试接口定义。
11+
* 包含各种鉴权场景的测试方法。
12+
*
13+
* @author 季聿阶
14+
* @since 2025-01-01
15+
*/
16+
public interface TestAuthInterface {
17+
/**
18+
* 测试Bearer Token静态鉴权。
19+
*
20+
* @return 鉴权测试结果
21+
*/
22+
String testBearerStatic();
23+
24+
/**
25+
* 测试Bearer Token参数驱动鉴权。
26+
*
27+
* @param token Bearer Token
28+
* @return 鉴权测试结果
29+
*/
30+
String testBearerDynamic(String token);
31+
32+
/**
33+
* 测试Basic Auth静态鉴权。
34+
*
35+
* @return 鉴权测试结果
36+
*/
37+
String testBasicStatic();
38+
39+
/**
40+
* 测试API Key Header静态鉴权。
41+
*
42+
* @return 鉴权测试结果
43+
*/
44+
String testApiKeyHeaderStatic();
45+
46+
/**
47+
* 测试API Key Query参数静态鉴权。
48+
*
49+
* @return 鉴权测试结果
50+
*/
51+
String testApiKeyQueryStatic();
52+
53+
/**
54+
* 测试API Key参数驱动鉴权。
55+
*
56+
* @param apiKey API Key值
57+
* @return 鉴权测试结果
58+
*/
59+
String testApiKeyDynamic(String apiKey);
60+
61+
/**
62+
* 测试动态Provider鉴权。
63+
*
64+
* @return 鉴权测试结果
65+
*/
66+
String testDynamicProvider();
67+
68+
/**
69+
* 测试自定义签名Provider鉴权。
70+
*
71+
* @return 鉴权测试结果
72+
*/
73+
String testCustomProvider();
74+
75+
/**
76+
* 测试方法级别覆盖接口级别鉴权。
77+
*
78+
* @return 鉴权测试结果
79+
*/
80+
String testMethodOverride();
81+
82+
/**
83+
* 测试多种鉴权组合(虽然我们说不支持多重鉴权,但可能有组合场景)。
84+
*
85+
* @param userToken 用户Token
86+
* @return 鉴权测试结果
87+
*/
88+
String testCombinedAuth(String userToken);
89+
}

0 commit comments

Comments
 (0)