Ktor 后端的 CORS 问题

Posted

技术标签:

【中文标题】Ktor 后端的 CORS 问题【英文标题】:CORS Issue With Ktor Backend 【发布时间】:2020-11-07 23:07:12 【问题描述】:

我正在创建一个全栈应用程序,后端使用 Ktor (Kotlin) 开发,前端使用 React (TypeScript)。后端托管在 Heroku 上,而前端仍在开发中,因此我在本地运行它。

在使用 Postman 进行测试时,该 API 可以正常运行并按预期工作。这是 Ktor 配置的摘录:

@Suppress("unused")
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) 

    install(CORS) 
        anyHost()
    

    install(StatusPages) 
        // Status pages configuration
    

    install(ContentNegotiation) 
        jackson 
            enable(SerializationFeature.INDENT_OUTPUT)
            disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)
        
    

    routing 
        // Declaration of routes
    

我已启用 CORS,允许每个主机访问资源。

在 React 应用程序中,我使用 axios 作为我的 HTTP 库。这是对服务器的请求的示例:

interface LoginModel 
    email: string;
    password: string;


interface TokenAuthModel 
    successful: boolean;
    access_token: string;


import * as axios from 'axios';

const requestConfig = 
    headers: 
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*'
    ,
        timeout: 15000
;

async login(login: LoginModel): Promise<TokenAuthModel | null> 
    const req = await axios.default.post('some-url', login, requestConfig);
    if (request.status === 200) 
        return request.data as TokenAuthModel;
    
    return null;

返回以下错误信息:

CORS 策略已阻止从源“http://localhost:3000”访问“https://app-name.herokuapp.com/some/endpoint”处的 XMLHttpRequest:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。

如上所述,该错误仅在从 React 前端发出请求时出现,而 Postman 调用按预期工作。

任何形式的帮助都将不胜感激。

【问题讨论】:

【参考方案1】:

我用这个来做cors:

install(CORS) 
        method(HttpMethod.Options)
        method(HttpMethod.Put)
        method(HttpMethod.Delete)
        method(HttpMethod.Patch)
        header(HttpHeaders.Authorization)
        header(HttpHeaders.ContentType)
        // header("any header") if you want to add any header
        allowCredentials = true
        allowNonSimpleContentTypes = true
        anyHost()
    

【讨论】:

【参考方案2】:

以下适用于我的设置(Ktor/axiom 也是):

fun Application.cors() 
    install(CORS) 
        method(HttpMethod.Options)
        method(HttpMethod.Put)
        method(HttpMethod.Delete)
        method(HttpMethod.Patch)
        header(HttpHeaders.Authorization)
        header(HttpHeaders.AccessControlAllowOrigin)
        allowNonSimpleContentTypes = true
        allowCredentials = true
        allowSameOrigin = true
        host(frontendHost, listOf("http", "https")) // frontendHost might be "*"
        logger.info  "CORS enabled for $hosts" 
    

可能有点过分,但我刚刚遇到了与No 'Access-Control-Allow-Origin' ... 相同的问题,这就是我解决它的方法。不需要 CORS 代理。

通过 ktor 源进行调试表明缺少 header(HttpHeaders.AccessControlAllowOrigin) 是主要问题。

【讨论】:

奇怪的是,这是必要的,因为该标头是 CORS 操作的基础,但添加 header(HttpHeaders.AccessControlAllowOrigin) 确实为我解决了这个问题。【参考方案3】:

您必须从 Kotlin 后端将您的来源(本地主机:3000)列入白名单。

【讨论】:

即使在将localhosthost("localhost:3000") 列入白名单后,客户端仍然存在相同的错误。

以上是关于Ktor 后端的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

ktor cors 标头中的 Access-Control-Allow-Origin 问题

Ktor 客户端的 JsonFeature 未解决

从 AngularJS 前端到 Spring rest 后端的 CORS 问题

Angular 2 应用程序到 Rails 5 后端的 CORS 问题

由于 Spring 5 中的 Access / CORS 问题,无法访问我的后端的 URL [重复]

使用 Next.js 和 Headless Wordpress 作为后端的 CORS 问题