我有一个简单的用户注册表单。
当用户填写表单并点击“#34;提交"我有一个JavaScript事件拦截提交,并使用AJAX调用下面的validate
方法来检查表单数据,然后再提交。如果表单数据正常,则继续提交,但如果不是,则取消提交并在页面上显示警告。这是进行实时客户端验证的简单方法。
# app/controllers/users_controller.rb
# Validates the form data. Returns an error message response in the format
# { response: "Invalid email format!" }
#
# A blank response means success
#
def validate
if request.xhr? || <request came from another method in this controller>
# Run various validations on input data and determine a response
# response_text = ...
render json: { response: response_text }
else
redirect_to root_path
end
end
def create
if JSON.parse(validate)["response"].blank?
User.create(...)
# Other stuff
end
end
但是,当提交最终通过并通过时,它会向POST
操作发送create
以创建新的User
。该方法再次调用validate
(重新验证的成本最低),以确保没有人绕过表单并直接向服务器提交恶意请求。
所以我的validate
方法必须同时响应(a)AJAX调用和(b)&#34;内部&#34;来自应用内的来电。对validate操作的所有其他调用应该只重定向到根路径。
我可以使用request.xhr?
判断调用是否是一个非常简单的AJAX调用。
如何检查操作是在内部调用而不是由用户调用?
退后一步,这是一个很好的验证通用方法吗?有什么想改进吗?
谢谢!
答案 0 :(得分:2)
Rails就会生成authenticity token。该令牌也存储在会话中,因此对用户不可见。收到请求后,您的应用程序将比较令牌以验证请求是否是从您的表单生成的。
TL; DR:别担心,你已经受到保护了。
答案 1 :(得分:1)
我没有具体的答案,但做有一些可能有用的信息。如果需要,我很乐意删除它......
AJAX调用和&#34;内部&#34;电话
您必须了解XHR请求只能 来自您的应用 - CORS (cross origin resource sharing)。
Ajax调用只能来自您自己的域名,因此不要认为恶意黑客可以运行某些刮刀或其他任何 - you choose允许哪些域发送XHR请求。
所以,当你打电话......
x,y,w,h = crdn
check_box = crop[y:y+h,x:x+w]
check_box_img_gray = cv2.cvtColor(check_box, cv2.COLOR_BGR2GRAY)
(_, thresh) = cv2.threshold(check_box_img_gray,200,255,cv2.THRESH_BINARY)
height,width = thresh.shape[:2]
tot_px = height * width
checked_box = cv2.countNonZero(thresh) / float(tot_px)
if checked_box < 0.6:
print "Found"
...作为验证的一部分,您需要在使用XHR时确定范围。
在同一张纸条上,您正在进行哪些验证?
如果您正在验证输入数据,Rails会在模型层处理此问题。我们已完成something similar(点击登录/注册顶部):
Rails的基本结构为MVC
,这意味着您的if request.xhr?
仅负责接收请求&amp;从中构建适当的数据对象。
因此,如果您正在验证&#34;输入,除了数据本身(由模型处理)还有什么可以验证?
当指定controller
时,Rails使用CSRF令牌为表单提交提供某些级别的身份验证。
-
您可以轻松使用以下内容:
@MarsAtomic
如果您之后将请求作为#app/controllers/users_controller.rb
class UsersController < ApplicationController
respond_to :js, :json, :html
def create
@user = User.new user_params
respond_with @user.save
end
end
从前端发送,则您将获回创建的用户或错误:
json
答案 2 :(得分:0)
在您的create方法中,如果它无效(如果它们跳过ajax验证),您希望返回@user
。
如果是这种情况,您不想执行User.create
,而是创建一个实例并尝试保存它。如果你做了这一切,你正在为create做正常的控制器动作,不需要在内部调用validate。
def create
@user = User.new(user_params)
if @user.save
# Other stuff
end
end
而且,创建一个json响应并解析它以查看对象是否有效并不是一个好习惯。相反,要么测试有效吗?或者只是尝试保存并找回真假。
换句话说 - 将您的验证方法与您的create方法分开。他们最终都会依赖valid?
。