在插件中重定向到外部网站?

我试图在用户登录 Discourse 后,调用一个外部 URL 来登录远程站点。我所需要做的只是重定向到远程站点上的某个 URL,该 URL 会在那里完成登录,然后再重定向回 Discourse。但当我这样做时,浏览器因为 CORS 问题拒绝重定向:

Access to XMLHttpRequest at 'https://SITE/api/sso/v2/sso/jwt?' (redirected from 'https://testing.literatehosting.com/session') from origin 'https://testing.literatehosting.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

该应用的开发人员表示,这是因为我的重定向方式有误(例如,是否使用了 AJAX 调用?),但这看起来和我在 此处 提到的提交中所看到的情况是一样的。

我(再次)束手无策了。

我无法确定是我太笨,还是他们确实需要发送 Access-Control-Allow-Origin 响应头(如果是这样,那他们的任何客户都无法正常工作?这似乎不太可能)。

以下是我的代码:

after_initialize do
  class ::SessionController
    def login(user)
      puts "\n\n\n\LOGIN happening!\n\n\n\n"
      session.delete(ACTIVATE_USER_KEY)
      log_on_user(user)

      if payload = cookies.delete(:sso_payload)
        sso_provider(payload)
      else
        if true # 插件已启用且拥有 API 密钥和 URL
          sign_into_thinkific(user)
        else
          render_serialized(user, UserSerializer)
        end
      end
    end

    def sign_into_thinkific(user)
      # 生成 payload 的相关操作

      redirect_to thinkific_sso_url(payload) # 也尝试过 redirect_to generate_url(thinkific_sso_url(payload))

    end

    def generate_url(url, params = {})
      puts "\n\n\nGenerate URL: #{url}\n\n\n"
      uri = URI(url)
      uri.query = params.to_query
      uri.to_s
    end

    def thinkific_sso_url(payload)
      current_url="https://#{GlobalSetting.hostname}/"
      url = "https://#{SiteSetting.thinkific_site_url}/api/sso/v2/sso/jwt?jwt=#{payload}"
      url += "&return_to=#{URI.escape(current_url)}" 

      url
    end

  end
end

编辑:开发人员分享了一个使用与我相同的 redirect_to 的 Rails 应用,他们声称这可以正常工作。Discourse 是否因为某些原因(例如,因为它运行在 Ember 内部?)对 redirect_to 的处理方式不同?

肯定是我漏掉了什么简单的地方。我最新的尝试代码如下:

      url = thinkific_sso_url(payload)
      redirect_location = "<!DOCTYPE html><html><head><meta http-equiv=\"Refresh\" content = \"5; url='#{url}'\" /></head><body>这是我的正文</body></html>"
      Rails.logger.info "正在重定向... #{redirect_location}"

      render plain: redirect_location

如果我将 redirect_location 的内容保存为文件并在浏览器中打开,我就能成功登录 Thinkific 并被重定向到 Discourse。遗憾的是,当我在浏览器中点击登录时,同样的方法却不起作用。

有人能帮帮我吗?

很抱歉点名@sam,但我觉得这里有个与 Discourse 相关且能快速解决的问题,需要你的帮助,而我已经为此折腾了两周。

我通过在中间插入一个代理让代码跑通了,但这似乎不是个理想的方案。

当我在重写的 SessionController 中尝试 redirect_to 外部站点时,遇到了 CORS 错误。而来自 Thinkific 的相同代码似乎没有这个问题。从 site_url/session 内部执行重定向有什么特殊之处吗?我是否需要通过 JavaScript 来执行重定向?如果是的话,能否指点我大致方向,说明该如何实现?

老实说,我不太清楚这里发生了什么。redirect_to 应该能够重定向到外部 URL。

哦,真糟糕。

确实会重定向,但会引发 CORS 违规。这很奇怪,因为看起来完全相同的重定向在他们的 Rails 示例代码中并不会导致 CORS 违规。我原本希望 Ember 内部的某种特殊机制能解决这个问题,或者有其他原因。

看来我指望这是个简单明显的错误是落空了。

非常感谢,我真的很感激你的帮助。

我相当确定,由于登录模态框是通过 AJAX 实现的(在 base_url/session 中),浏览器会拒绝执行 redirect_to,除非对方发送了 CORS 头。

我认为我需要某种方法(我完全不知道该如何描述)来跳出 AJAX 环境,使得对浏览器而言这看起来像是一次正常的重定向,而不是 AJAX 中的重定向。

或者,有没有办法让登录页面变为非 AJAX 页面?

@pfaffman

这种情况有进展吗?我在 asp.net core Web API 中使用 Discourse SSO 登录时也遇到了同样的问题。

Angular 应用浏览器在请求从 API 重定向到 Angular 应用后(Discourse 已成功返回响应),抛出了“缺少 accept 控制头”的错误。

Angular Web 应用 → asp.net API → API 调用 Discourse SSO → Discourse 将值返回给 asp.net 服务器 API → API 服务器将回调重定向到 Angular 应用 URL → 浏览器报错,提示由于缺少“Access-Control-Allow-Origin”头,Discourse URL 无法访问。

image

Discourse 和 asp.net API Web 服务器上的所有 CORS 设置均已正确配置。

这听起来很像你之前遇到的问题。希望你能指点一下如何解决。