我创建了一个端点 /api/chat
,调用时会向 OpenAI API(已付费且 API KEY 有效)发出另一个请求。
我在 Postman 中测试该端点,首先请求我的 /auth/login
端点以获得一个有效的 JWT Token,然后将其复制到 /api/chat
的 Authorization
Header 中,最后发起请求(登录的
JWT Token 100% 有效,而且在所有其他端点中都没问题)。
当请求 /api/chat
时,大约需要 1.5-2 秒。在第一秒钟,IDE 控制台输出了正常的内容,表明请求已发出,接着输出 OpenAI API 的响应。到这里一切都没问题。但随后 Postman 返回的状态码是 403,而不是 200 OK,我 IDE 控制台输出的内容都没有问题。
我尝试在 SecurityConfig
中把 /api/chat
端点设置为公开的。这样倒是没问题,但是问题更大了,相当于任何人都可以访问我的 API(我的 ChatGPT 充了钱的)。
这个问题我折腾了很久,包括上网搜索、问 GPT,但一无所获。我感觉是 Spring Security 出了问题,因为只有将端点添加到 SecurityConfig
中的 .permitAll()
List(公开这个端点)中,它才能返回 200 OK。
我的一一些代码如下:
Security 配置:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/auth/**", "/", "/index.html", "/manifest.json", "/static/**", "/*.js", "/*.jsx", "/*.css", "/home", "/log-in", "/sign-up")
.permitAll()
.requestMatchers("/auth/signup", "/auth/login").anonymous()
.anyRequest()
.authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
Controller:
@PostMapping
public Mono<ResponseEntity<String>> getChatCompletion(@RequestBody ChatRequest chatRequest, @RequestHeader HttpHeaders headers) {
return openAiService.getChatCompletion(chatRequest.getInput())
.map(response -> {
logger.info("Response: {}", response); // 记录响应
return ResponseEntity.ok(response);
})
.defaultIfEmpty(ResponseEntity.noContent().build());
}
public static class ChatRequest {
private String input;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
}
Service:
public Mono<String> getChatCompletion(String userInput) {
String requestBody = String.format("""
{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "MY CONTENT"
},
{
"role": "user",
"content": "%s"
}
],
"temperature": 1,
"max_tokens": 256,
"top_p": 1,
"frequency_penalty": 0,
"presence_penalty": 0
}
""", userInput);
logger.info("Sending request to OpenAI with body: {}", requestBody);
return this.webClient.post()
.uri("/chat/completions")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + openaiApiKey)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(String.class)
.doOnNext(response -> logger.info("Received response from OpenAI: {}", response))
.doOnError(WebClientResponseException.class, error -> {
logger.error("Error response from OpenAI: {}", error.getResponseBodyAsString());
})
.doOnError(error -> logger.error("Error occurred: ", error));
}
我的 Postmant 请求(应该和问题没啥关系):
{
input: "MY INPUT"
}