【问题标题】:Serve static websites with Rails based on user session基于用户会话使用 Rails 服务静态网站
【发布时间】:2014-07-30 18:12:30
【问题描述】:

是否可以根据用户登录(以用户为中心的路由)将用户从 Rails 3 / 4 路由限制到服务器完整网站?我大致考虑将不同的静态网站放在应用程序的子目录中,并让主根目录下的用户可以访问它们(通过登录保护)。

如果没有用户登录,则使用简单的登录掩码来识别用户,例如与设计。我正在考虑简化静态页面的暂存部署,例如由中间人生成。最好有一个简单的 capistrano 任务来部署到 rails 应用程序,而不是创建子域、ftp 上传等。

在 / 下挂载静态页面的原因是,大多数静态网站生成器都希望页面在 / 下,我想避免资产中的绝对/相对路径出现问题。

更具体一点:

案例 1) 用户未登录 -> 任何路由都要求进行身份验证

案例 2) 用户已登录,静态内容从 /app/sites/site1 提供(安装在 "/" )

案例 3) 另一个用户已登录,静态内容从 /app/sites/site2 提供(安装在 "/" )

所服务的网站取决于用户个人资料。

【问题讨论】:

  • 请添加更多信息。一个具体的例子会很棒。有几种方法可以解决这个问题。
  • 我想知道 Rails 在这方面是不是有点矫枉过正,也许你应该考虑像 Sinatra 这样的东西:sinatrarb.com
  • 你能澄清一下这个问题吗?
  • 你有什么收获吗?

标签: ruby-on-rails


【解决方案1】:

回答我自己的问题:是的,这是可能的。

就我而言,Rails 并不过分。我与我们基于 Rails 的项目管理系统无缝集成。我正在安装 Sinatra-App 作为 Web 服务器,使用基于用户会话的不同公共 URL。 session 是通过唯一的 token 生成的,这样用户就可以一个接一个地查看不同的静态项目。

routes.rb:

constraints(:subdomain => /preview/) do
    mount SinatraWrapper => "/"
end

注意:我在这里使用约束来检查子域。每个静态预览都被重定向到不同子域下的同一个应用程序。

Sinatra 包装器:

# a super-trivial Sinatra-based webserver
# for static content
require 'sinatra/base'

class SinatraWrapper < Sinatra::Base
  before '/*' do
    SinatraWrapper.set_site(session[:site])
  end

  def self.set_site(site)
    rootPath = File.expand_path("#{Rails.root}/sites/#{site}/")
    set :public_folder, "#{rootPath}/current/build/"
  end

  configure do
    set :static, true
    set :static_cache_control, [:public, :no_store, :no_cache, :must_revalidate, :max_age => 0, :expires => "Fri, 01 Jan 1990 00:00:00 GMT"]
  end

  set_site("default")

  # route to starting page (index.html)
  get "/" do
    redirect "/index.html"
  end

  # route to custom error page (404.html)
  not_found do
    redirect "/404.html"
  end

end

注意:我正在通过 capistrano 将静态项目的更新部署到 rails 应用程序中。构建通过Middleman 远程执行(我们可以在此处使用任何其他静态站点生成器)。另一个实例检查我们的 git 存储库中“预览”分支中的更新并在其上运行测试。通过所有测试后,将自动执行并部署构建。

这里是棘手的一点,对两个不同的子域使用不同的行为,但相同的会话:

# static_pages_controller.rb:

def preview

    if request.subdomain == "preview" or Rails.env.development? # local dev: no subdomains
      @static_page = StaticPage.find(params[:id])
      session[:site] = @static_page.slug || "default" # using a sha-slug for every static project
      redirect_to "/" # redirect to root. we have a valid session now.
    else
      # we are NOT on the preview subdomain, so we need to redirect to proper subdomain
      @project = Project.find(params[:project_id])
      @static_page = StaticPage.find(params[:id])
      redirect_to preview_url(project_id: @project.id, id: @static_page.id, token: @static_page.slug).sub("plattform", "preview")
    end
end

注意:我有很多静态页面的项目。我们对平台上的每个静态页面都有一个预览操作。如果您使用来自平台的链接点击预览操作,您将被重定向到预览子域并设置您的会话。我们的身份验证允许我们

  • 向客户发送带有身份验证令牌 (SHA-Slug) 的匿名链接
  • 并通过数据库进行身份验证

这个系统我们用了半年了,很满意!客户可以立即看到预览。到目前为止,我们还没有遇到任何严重的问题,除了必须正确设置缓存标头以确保每次重新加载页面时都加载新内容。这会减慢体验,但我们总是可以争论,这是一个预览。老实说,大多数客户不知道加载时间。

无论如何,我不能 100% 确定我的“崩溃”缓存的实现是否是完美的解决方案。任何提示将不胜感激。我只在 Chrome 和 Safari 中遇到问题(非常罕见),您需要多次重新加载页面,直到显示新内容。

另一个有趣的问题是安全性。我认为相对安全。但我不是安全专家。有什么顾虑吗?

我们仅在内部使用此平台。没有产品,所以我们不会非常温和地处理错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    • 2013-01-21
    • 2014-04-27
    • 1970-01-01
    • 2020-10-18
    相关资源
    最近更新 更多