programing

Rails 3.2.11 및 RSpec을 사용한 원시 JSON 데이터 POST

golfzon 2023. 3. 25. 12:03
반응형

Rails 3.2.11 및 RSpec을 사용한 원시 JSON 데이터 POST

응용 프로그램이 이 부정 이용에 취약하지 않음을 확인하기 위해 RSpec에서 이를 커버하는 컨트롤러 테스트를 작성하려고 합니다.그러기 위해서는 raw JSON을 투고할 수 있어야 하는데, 아직 그 방법을 찾지 못한 것 같습니다.몇 가지 조사를 하면서, 저는 적어도 이전에는 이러한 방법을 사용할 수식을 수행했다고 판단했습니다.RAW_POST_DATAheader, 그러나 이것은 더 이상 작동하지 않는 것 같습니다.

it "should not be exploitable by using an integer token value" do
  request.env["CONTENT_TYPE"] = "application/json"
  request.env["RAW_POST_DATA"]  = { token: 0 }.to_json
  post :reset_password
end

Params 해시를 보면 토큰은 전혀 설정되어 있지 않고, 단지 다음과 같이 되어 있습니다.{ "controller" => "user", "action" => "reset_password" }XML을 사용하려고 해도, 일반 포스트 데이터만 사용하려고 해도, 어느 경우라도 기간이 설정되어 있지 않은 것 같습니다.

최근의 Rails 취약성으로 인해 파라미터의 해시 방식이 변경된 것은 알고 있습니다만, 아직 Raw data를 RSpec을 통해 게시할 수 있는 방법이 있습니까?직접 사용해도 될까요?Rack::Test::Methods?

지금까지 제가 알 수 있는 한 컨트롤러 사양 내에서 Raw POST 데이터 송신은 불가능하게 되었습니다.단, 요청 사양에서는 매우 쉽게 실행할 수 있습니다.

describe "Example", :type => :request do
  params = { token: 0 }
  post "/user/reset_password", params.to_json, { 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' }
  #=> params contains { "controller" => "user", "action" => "reset_password", "token" => 0 }
end

Raw JSON을 컨트롤러 액션(레일 3+)으로 송신하는 방법은 다음과 같습니다.

예를 들어 다음과 같은 루트가 있다고 합시다.

post "/users/:username/posts" => "posts#create"

그리고 몸이 json이기를 기대한다고 가정해 보겠습니다.

JSON.parse(request.body.read)

테스트 결과는 다음과 같습니다.

it "should create a post from a json body" do
  json_payload = '{"message": "My opinion is very important"}'
  post :create, json_payload, {format: 'json', username: "larry" }
end

{format: 'json'}그것을 가능하게 하는 마법입니다.또한 TestCase #post http://api.rubyonrails.org/classes/ActionController/TestCase/Behavior.html#method-i-process의 소스를 보면 액션 뒤에 첫 번째 인수(json_post)가 있고 문자열일 경우 raw post body로 설정되며 나머지 arg는 정상적으로 해석됩니다.

rspec은 Rails 테스트 아키텍처 위에 있는 DSL일 뿐이라는 점도 중요합니다.post위의 메서드는 Action Controller입니다.: 일부 rspec 발명이 아닌 Test Case #post.

컨트롤러 테스트에서는 RAW_POST_DATA를 명시적으로 설정하고 있습니다.

before do
  @request.env['RAW_POST_DATA'] = payload.to_json
  post :my_action
end

레일 5의 예:

RSpec.describe "Sessions responds to JSON", :type => :request do

  scenario 'with correct authentication' do
    params = {id: 1, format: :json}
    post "/users/sign_in", params: params.to_json, headers: { 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' }
    expect(response.header['Content-Type']).to include 'application/json'
  end
end

다음으로 raw json 데이터를 전송하는 컨트롤러 테스트의 전체 작업 예를 나타냅니다.

describe UsersController, :type => :controller do

  describe "#update" do
    context 'when resource is found' do
      before(:each) do
        @user = FactoryGirl.create(:user)
      end

      it 'updates the resource with valid data' do
        @request.headers['Content-Type'] = 'application/vnd.api+json'
        old_email = @user.email
        new_email = Faker::Internet.email
        jsondata = 
        {
          "data" => {
            "type" => "users",
            "id" => @user.id,
            "attributes" => {
              "email" => new_email
            }
          }
        }

        patch :update, jsondata.to_json, jsondata.merge({:id => old_id})

        expect(response.status).to eq(200)
        json_response = JSON.parse(response.body)
        expect(json_response['data']['id']).to eq(@user.id)
        expect(json_response['data']['attributes']['email']).to eq(new_email)
      end
    end
  end
end

중요한 부분은 다음과 같습니다.

@request.headers['Content-Type'] = 'application/vnd.api+json'

그리고.

patch :update, jsondata.to_json, jsondata.merge({:id => old_id})

첫 번째는 콘텐츠유형이 요구에 맞게 올바르게 설정되어 있는지 확인합니다.이것은 매우 간단합니다.두 번째 부분은 몇 시간 동안 골칫거리였습니다.처음 접근 방식은 상당히 달랐습니다만, Rails의 버그가 있는 것이 판명되어 기능 테스트에서는 Raw Post 데이터를 송신할 수 없게 되었습니다(단, 통합 테스트에서는 송신할 수 있습니다).이 회피책은 보기 흉한 것이지만(레일 4.1.8 및 r-specails 3.0.0에서는 유효합니다).

레일 4의 경우:

params = { shop: { shop_id: new_subscrip.shop.id } }
post api_v1_shop_stats_path, params.to_json, { 'CONTENT_TYPE' => 'application/json',
                                                     'ACCEPT' => 'application/json' }

@ @daniel-vandersluis의 에 대한 약간의 .rails 3.0.6, 를 사용하여, 를 참조해 주세요.rspec 2.99 ★★★★★★★★★★★★★★★★★」rspec-rails 2.99:

describe "Example", :type => :request do
  params = { token: 0 }
  post "/user/reset_password", params.merge({format: 'json'}).to_json, { 'CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json' }
end

HTTP_ACCEPT큰가 없습니다(header는 header로 할 수).HTTP_ACCEPT 그냥 '그냥'일 수도 있어요.ACCEPT하지만, 제 경우, 기능이 작동하려면 , 파라메스가 다음과 같이 되어 있을 필요가 있습니다..merge({format: 'json'}) ★★★★★★★★★★★★★★★★★」.to_json

또 다른 변형:

describe "Example", :type => :request do
  params = { token: 0 }
  post "/user/reset_password", params.merge({format: 'json'}).to_json, { 'CONTENT_TYPE' => Mime::JSON.to_s, 'HTTP_ACCEPT' => Mime::JSON }
end

it it를 한다.Mime::JSON ★★★★★★★★★★★★★★★★★」Mime::JSON.to_sapplication/json헤더값으로 지정합니다.

언급URL : https://stackoverflow.com/questions/14775998/posting-raw-json-data-with-rails-3-2-11-and-rspec

반응형