2

我有一个 Rails 3.2 应用程序,需要用户登录 (current_user) 才能访问事件页面,这些页面是子域。我正在使用设计进行身份验证。

如果我提供了指向事件页面的直接链接,有什么方法可以让用户一次性访问它?然后,如果他们尝试访问不同的活动页面,或者如果他们离开并在未来某个日期返回同一活动页面,我希望他们被提示登录(或注册)。

我在railscasts上看过来宾帐户的一集,但似乎用户可以继续以来宾身份登录,而无需使用这种方法进行注册。

这是我的事件控制器代码:

def show
    @event = Event.find_by_name(request.subdomain)
    if params[:id].present?
      @event = Event.find(params[:id])
    end
    # if @event.present? and @event.videos.present?
      @video = Video.find_by_id(params[:video]) || @event.videos.first
    # else 
    #   @video = @event.videos.first
    # end
    # @json = Event.all.to_gmaps4rails 
    if @user = current_user
    else 
      flash[:alert] = "Please sign in first"
      redirect_to sign_up_url(:subdomain => false)
    end
end

感谢您的任何帮助/建议...

编辑:只是为了提供更多上下文:

  1. 我将尝试每周将很多用户吸引到这个活动页面,如果我只是通过社交媒体和电子邮件等发送一个链接,我不确定将单独的哈希硬编码到网址中是否可行/实用.

  2. 由于用户将单击此链接并直接进入相关页面,因此不会触发任何操作来创建单独的访客模型,因此我认为答案必须基于会话,在现有用户模型中添加一些列,但确保每个用户只使用一次。我在想也许一个IP地址会起作用?

4

5 回答 5

4

一种解决方案是使用 url 对一次性哈希进行硬编码,而不是设置会话变量,如下所示:

http://site.com/event?access_id=AKJHDA23fdsank

然后,在访问事件时,访问代码被删除。这将需要管理数据库中的访问代码,但具有万无一失的额外好处。

您可以非常简单地创建一个 api url 来生成这些链接以简化共享过程。

大多数其他事情都很容易上当。

于 2013-08-28T20:27:46.330 回答
3

最有先见之明的解决方案是为访客用户创建一个会话变量,其中包含一个布尔值,指示他们是否访问过该页面(如果他们没有访问过,则启用访问,反之亦然):

# in your controller
before_filter :check_guest, :only => :show

private

def check_guest
  # if user isn't logged in
  if current_user.nil? 
    # if user has already viewed, redirect
    if session[:viewed] == true
      flash[:alert] = "Please sign in first"
      redirect_to sign_up_url(:subdomain => false)
    # if user hasn't viewed, allow access, but flag as having viewed
    else
      session[:viewed] = true
    end
  end
end

尽管使用会话是解决此特定问题的事实上的方法,但其实施存在限制:

  • 会话必须保持有效才能跟踪访客访问
  • 特定于浏览器(因此浏览器上的多个用户将共享同一个会话)
于 2013-08-28T20:19:02.290 回答
1

您可以使用 feature_flags gem 设置布尔值:

https://rubygems.org/gems/feature_flags

于 2013-08-28T20:24:32.950 回答
0

我不知道对此有一个预先构建的解决方案,但实施起来应该不会太难。我会做类似的事情:

class GuestPass < ActiveRecord::Base

  belongs_to :event

  # the guest_passes table has a `code` column that contains a long arbitrary string token
end

class Event < ActiveRecord::Base

  has_many :guest_passes

  def authenticate_guest_pass!(token)
    return false unless token
    guest_passes.where(code: token).first
  end

end

class EventsController < ActiveRecord::Base

  before_action :load_event, only: [ :show ]
  before_action :validate_guest_pass, unless: current_user

  private

  def load_event
    @event = Event.find(params[:id])
  end

  def validate_guest_pass
    pass = @event.authenticate_guest_pass!(params[:pass])
    if pass
      pass.delete
    else
      # redirect to sign in or whatever
    end
  end

end

然后您只需生成GuestPass记录并将它们粘贴在您提供的链接中:它们看起来像/events/1?pass=xyzzy

(这里的代码可以进行一些清理;我并不是说它很漂亮。但这是第一次通过。)

于 2013-08-28T20:32:45.933 回答
0

这是我对 zeantsoi 解决方案稍作修改的版本,即使用户退出浏览器会话,它也会持续存在。

def check_guest
  #if user is logged in
  unless current_user 
    @event = Event.find_by_name(request.subdomain)
    #if user has already viewed, redirect
    if @event.guest_ip_address == request.remote_ip
      flash[:alert] = "Please sign in first"
      redirect_to sign_up_url(:subdomain => false)
    #if user hasn't viewed, allow access, but flag as having viewed and store their ip address in the event model so it knows not to show the page again unless current_user
    else
      session[:viewed] = request.remote_ip
      @event.guest_ip_address = session[:viewed]
      @event.save!
    end
  end
于 2013-08-28T23:48:16.710 回答