直接访问 url 是否与通过 link 导航具有相同的效果?

Does directly visiting a url have the same effect as navigating via a link?

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

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 来绕过这个吗?如果是这样,我该如何预防?

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

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

为了更简单的解决方案,您可以为每个用户添加一个会话令牌,并检查 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 保存在数据库中并进行检查