直接访问网址与通过链接导航具有相同的效果吗?

时间:2015-01-21 21:11:43

标签: ruby-on-rails ruby ruby-on-rails-4 path routes

我有一个记录用户的投票系统' ip地址,用户只能投票一次。如果投票数组包含用户的IP地址,则投票链接将不会显示给用户:

show.html.erb

<% if !ip_array.include? request.remote_ip %>
  <%= link_to "Vote!", vote_user_path(@user) %>
<% else %>
  You've already voted!
<% end %>

users_controller.rb

def vote
  @user = User.find(params[:id])
  @user.votes = @user.votes + 1
  @user.save
end

但是用户不能直接转到www.my_website.com/users/:id/vote来绕过这个?如果是这样,我该如何防止这种情况?

2 个答案:

答案 0 :(得分:3)

阻止它的方法是将验证放在控制器操作中,而不是放在视图中(或除此之外)。

before_action :ensure_not_voted

def vote
  @user = User.find(params[:id])
  @user.votes = @user.votes + 1
  @user.save
end

protected

def ensure_not_voted
  # perform the check and stop on failure
  # already_voted is a fake function, replace it with your real check
  if already_voted
    halt(403)
  end
end

答案 1 :(得分:0)

对于更简单的解决方案,您可以为每个用户添加会话令牌,并检查ip是否包含特定令牌,例如

添加before_filter :auth, :only => [:vote]

def vote
  @user = User.find(params[:id])
  @user.votes = @user.votes + 1
  @user.save
  session[:token] = request.remote_ip
end


private

  def auth
        @ip = session[:token].to_s

        if @ip != nil
            redirect_to :back
            flash[:notice] = "You have already voted"
            return false
        else
            return true
        end
  end

用户可以删除cookie再次投票(很少有人可以),因为这种情况下你可以将ip保存在数据库中并检查它