我有一个记录用户的投票系统' 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
来绕过这个?如果是这样,我该如何防止这种情况?
答案 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保存在数据库中并检查它