Rails [求助] 第三方网站 post 请求本网站,出现 Can't verify CSRF token authenticity 错误。

Sylor-huang · 2019年03月13日 · 最后由 Sylor-huang 回复于 2019年03月14日 · 1921 次阅读

我现在用的是第三方收款软件,就是监控手机收款提示,然后,post 数据到我的服务器,我根据 post 回来的数据判断是否成功支付。

但是我现在碰到的问题是,post 到我的方法时,不带authenticity_token,一直出现错误:Can't verify CSRF token authenticity.

我的 post method:

class FundsController < ApplicationController

  def success_recharge   #method post
    @r_user = User.find_by_id(params[:order_uid])
    return_array = params[:aoid] +params[:order_id]+params[:order_uid]+params[:price]+params[:pay_price]+'1c9a3e0eba564d68831bbeefb2ae5f72'   #第三方返回的数据
    sign = make_md5_string(return_array)
    if sign == params[:sign] 
      respond_to do |format|
        format.html {
          redirect_to funds_user_path(@r_user)
          flash[:success] = "充值成功"
        }
        format.json{
          render json: {status: :ok}
        }
      end
    else
      redirect_to funds_user_path(@r_user)
      flash[:danger] = "充值失败,#{check_s[:status]}"
    end
  end

end

我的users_controller.rb:

class UsersController < ApplicationController
  before_action :logged_in_user

  def funds

  end

end

logged_in_user 方法:

module SessionsHelper
  def logged_in_user
    unless logged?
      store_location
      flash[:danger] = "请先登录"
      redirect_to login_path
    end
  end

end

如果在FundsController中添加skip_before_action :verify_authenticity_token, :only => [:success_recharge],那就不能redirect_tofunds_user_path(@r_user),而是到login_path,

请问大家,我该怎么修改。非常感谢~~~!

在 FundsController 类名下添加下面的代码试试看?

protect_from_forgery :except => [:success_recharge]

是不是 funds_user_path 又触发了 logged_in_user filter

@Rei 嗯嗯,是的。提示错误

Redirected to http://127.0.0.1:3000/login
Filter chain halted as :logged_in_user rendered or redirected
Completed 302 Found in 2ms (ActiveRecord: 0.4ms)

@baboon 添加了一样会提示以上错误的

Sylor-huang 回复

所以你要考虑 funds_user_path 这个 action 需不需要 logged_in_user?如果需要的话第三方如何处理。

@Rei 我觉得这个还是需要的,我现在在想用 js.erb 处理,然后由用户手动刷新。

第三方的 post 请求,应该是后台调用吧?不是用户请求,不需要 redirect 到用户的页面。

如果是用户跳转回网站应该是 get 请求。

@Rei 初步流程是,由用户发起 post 请求到第三方,然后第三方 post,返回数据,我需要根据返回的数据,判断用户是否充值成功,如果成功就 redirect 到用户的发起充值页面,并做提示。

@Rei ,你好,我用 format.js,然后就一直提示 Unknown Format 406 错误,我这是哪里有错误呢?能不能麻烦你帮我看下。非常感谢。

class FundsController < ApplicationController

  def success_recharge   #method post
    @r_user = User.find_by_id(params[:order_uid])
    return_array = params[:aoid] +params[:order_id]+params[:order_uid]+params[:price]+params[:pay_price]+'1c9a3e0eba564d68831bbeefb2ae5f72'   #第三方返回的数据
    sign = make_md5_string(return_array)
    check_uri = URI.parse("https://xxx/api/query/#{aoid}")
    response = Net::HTTP.get(check_uri)
    check_s = JSON.parse(response)
    @success_flash = check_s["status"]
    s_status = %w(payed success fee_error expire)
    respond_to do |format|
      if sign == params[:sign] && s_status.include?(@success_flash)
        format.json{render json: { status: :ok }}
        format.js
      else
        format.html{
          redirect_to home_path
          flash[:danger] = "出现错误:#{t(@success_flash)},请您及时联系我们!"
        }
        format.json{render json: { status: :unprocessable_entity }}
      end
    end

end

// success_recharge.js.erb

var s_modal = $("#recharges_accounts")
s_modal.find(".modal-body").html("<%= j render(partial: "funds/success_html",locals: {message:@success_flash}) %>")

Sylor-huang 回复

你弄清楚这个请求是服务器发送的还是用户浏览器发送的。

我猜这是服务器发送的,只能用 format.html,你的 respond_to if true 路径上没有处理这个类型。

是第三方服务器发送的,这个就非得用 format.html 吗?

请问:如何在 ruby 代码中读取 yml 的内容?比如 yml 中 name 有:

- WALKER
- WALLACE
- WALLY
- WALTER
- WALTON
- WARD

我想随机生成 100 个数据 并且数据名字是这里的:

AML::load(File.read(Rails.root.to_s + '/config/users.yml'))
    ::Meter.create(:name=>)  #这里怎么写随机生成的100个数据  并且将名字塞进去??
Sylor-huang 回复

更正一下,要用什么 format 得看第三方的文档。

format 是根据 client 的 accept content 头来区分返回内容,但客户端能处理什么内容是客户端定的,不是在 Rails 里面指定 format.js 客户端就能解析 js。

@Rei 嗯嗯好的,非常感您的耐心回答。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号