成功登录(状态码200)将导致状态码401 GET请求

时间:2019-08-07 18:45:27

标签: javascript ruby-on-rails vue.js http-status-code-401

最近,我在heroku上部署了Rails后端和Vue前端。几天前一切似乎都很好,直到我今天尝试登录Web应用程序为止。登录后,我立即收到401响应,因为登录后,该应用程序应该显示数据库中的漫画书。

对于背景,我正在通过webcrunch在youtube上关注Vue.js / Rails教程。在本教程中,localStorage与JWTSessions和axios一起使用。我使用了以下问题,但没有提供我正在寻找的HttpGet 401 status code followed by 200 status code答案。我也尝试在我的api网址中添加尾部斜杠,但这不能解决问题。在vue前端中,本教程还使用了axios / index.js文件,该文件配置axios请求的实例。

application_controller.rb

class ApplicationController < ActionController::Base
  include JWTSessions::RailsAuthorization
  rescue_from JWTSessions::Errors::Unauthorized, with: :not_authorized

  private

    # access current user
    def current_user
      @current_user ||= User.find(payload['user_id'])
    end

    def not_authorized
      # render actual data back since no view
      render json: { error: 'Not authorized' }, status: :unauthorized
    end
end

signin_controller.rb(不包含signup_controller.rb,因为它们相似)

class SigninController < ApplicationController
  before_action :authorize_access_request!, only: [:destroy]
  skip_before_action :verify_authenticity_token

  def create
    user = User.find_by!(email: params[:email])
    if user.authenticate(params[:password])
      payload = { user_id: user.id }
      # allow user to log in again if failed attempt
      session = JWTSessions::Session.new(payload: payload, refresh_by_access_allowed: true)
      tokens = session.login
      response.set_cookie(JWTSessions.access_cookie,
                        value: tokens[:access],
                        httponly: true,
                        secure: Rails.env.production?)
      render json: { csrf: tokens[:csrf] }
    else
      not_authorized
    end
  end

  def destroy
    session = JWTSessions::Session.new(payload: payload)
    session.flush_by_access_payload
    render json: :ok
  end

  private

  def not_found
    render json: { error: "Cannot find email/password combination" }, status: :not_found
  end
end

/config/initializers/cors.rb

Rails.application.config.middleware.insert_before ActionDispatch::Static, Rack::Cors do
  allow do
    origins ['https://gem-mint-client.herokuapp.com', 'http://gem-mint-client.herokuapp.com']

    resource '*',
      headers: :any,
      credentials: true,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

/frontend/src/backend/axios/index.js

import axios from 'axios'

const API_URL = 'https://gem-mint-server.herokuapp.com'

const securedAxiosInstance = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

const plainAxiosInstance = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

securedAxiosInstance.interceptors.request.use(config => {
  const method = config.method.toUpperCase()
  if (method !== 'OPTIONS' && method !== 'GET') {
    config.headers = {
      ...config.headers,
      'X-CSRF-TOKEN': localStorage.csrf
    }
  }
  return config
})

securedAxiosInstance.interceptors.response.use(null, error => {
  if (error.response && error.response.config && error.response.status === 401) {
    return plainAxiosInstance.post('/refresh', {}, { headers: { 'X-CSRF-TOKEN': localStorage.csrf } })
      .then(response => {
        localStorage.csrf = response.data.csrf
        localStorage.signedIn = true
        let retryConfig = error.response.config
        retryConfig.headers['X-CSRF-TOKEN'] = localStorage.csrf
        return plainAxiosInstance.request(retryConfig)
      }).catch(error => {
        delete localStorage.csrf
        delete localStorage.signedIn

        location.replace('/')
        return Promise.reject(error)
      })
  } else {
    return Promise.reject(error)
  }
})

export { securedAxiosInstance, plainAxiosInstance }

我当时正在处理CORS问题,但我认为情况并非如此。我的CORS问题是因为我在浏览器标题中输入的URL不带https,因此要解决的问题是我同时将https和http url都包括在内。我期望的最终结果是您应该能够登录或注册,而不会由于未授权而立即注销。如果需要更多代码,请告诉我。预先谢谢你。

Edit2:comics_controller.rb

module Api
  module V1
    class ComicsController < ApplicationController
      before_action :authorize_access_request!
      before_action :set_comic, only: [:show, :edit, :update, :destroy]
      skip_before_action :verify_authenticity_token

      # GET /comics
      # GET /comics.json
      def index
        @comics = current_user.comics.all

        render json: @comics
      end

      # GET /comics/marvel
      def marvel
        # start connection to Marvel
        @client = Marvel::Client.new

        # keys to configure marvel api
        @client.configure do |config|
          config.api_key = ENV['PUBLIC_MARVEL_API']
          config.private_key = ENV['PRIVATE_MARVEL_API']
        end

        # store parameters to send as request
        # set limit to 100, otherwise server error if over
        @args = {limit: '100'}

        # marvel api creator parameter needs to be inputted as an id
        # find creator id
        if params[:creators] != ''
          @creator = @client.creators(nameStartsWith: params[:creators])
          @args[:creators] = @creator[0][:id]
        end

        # check if other params were inputted and add to @args object
        if params[:issueNumber] != ''
          @args[:issueNumber] = params[:issueNumber]
        end
        if params[:title] != ''
          @args[:titleStartsWith] = params[:title]
        end
        if params[:startYear] != ''
          @args[:startYear] = params[:startYear]
        end

        # find comics based on given parameters
        @comics = @client.comics(@args)

        render json: @comics
      end

      # GET /comics/price
      def price
        EbayRequest.configure do |config|
          config.appid = ENV['EBAY_APP_PROD_ID']
          config.certid = ENV['EBAY_CERT_PROD_ID']
          config.devid = ENV['EBAY_DEV_PROD_ID']
          config.runame = ENV['EBAY_PROD_RUNAME']
          config.sandbox = false
        end
        @items = EbayRequest::Finding.new.response('findItemsAdvanced', categoryId: '63', keywords: params[:query])

        render json: @items
      end

      # GET /comics/1
      # GET /comics/1.json
      def show
        @comic
        render json: @comic
      end

      # GET /comics/new
      def new
        @comic = Comic.new
      end

      # GET /comics/1/edit
      def edit
      end

      # POST /comics
      # POST /comics.json
      def create
        @comic = current_user.comics.build(comic_params)

        respond_to do |format|
          if current_user.comics.exists?(title: @comic.title)
            # access first object
            found_book = current_user.comics.where(title: @comic.title)[0]
            quantity = found_book.quantity
            # sum up previous quantity with additional quantity
            found_book.update_attribute(:quantity, quantity + @comic.quantity)
            format.html { redirect_to '/', notice: 'Invite was successfully created' }
            format.json {
              render json: @comic, status: :created, location: api_v1_comic_url(@comic)
            }
          else
            # if no records exist, create a new one
            if @comic.save
              format.html { redirect_to '/', notice: 'Invite was successfully created' }
              format.json {
                render json: @comic, status: :created, location: api_v1_comic_url(@comic)
              }
            else
              format.html { render :new }
              format.json {
                render json: @comic.errors, status: :unprocessable_entity
              }
            end
          end
        end
      end

      # PATCH/PUT /comics/1
      # PATCH/PUT /comics/1.json
      def update
        respond_to do |format|
          if @comic.update(comic_params)
            format.html
            format.json {
              render json: @comic, status: :created, location: api_v1_comic_url(@comic)
            }
          else
            format.html { render :new }
            format.json {
              render json: @comic.errors, status: :unprocessable_entity
            }
          end
        end
      end

      # DELETE /comics/1
      # DELETE /comics/1.json
      def destroy
        @comic.destroy
      end

      private

        # Use callbacks to share common setup or constraints between actions.
        def set_comic
          @comic = current_user.comics.find(params[:id])
        end

        # Never trust parameters from the scary internet, only allow the white list through.
        def comic_params
          params.require(:comic).permit(:title, :issue, :year, :image, {:creators => []}, :quantity, :description)
        end
    end
  end
end

编辑:日志输出

at=info method=POST path="/signin" host=gem-mint-server.herokuapp.com request_id=a6f30e31-8f19-4c7f-9381-4135efb0f648 fwd="75.18.100.151" dyno=web.1 connect=1ms service=307ms status=200 bytes=1162 protocol=https
2019-08-07T21:15:03.882596+00:00 app[web.1]: I, [2019-08-07T21:15:03.882487 #4]  INFO -- : [a6f30e31-8f19-4c7f-9381-4135efb0f648] Completed 200 OK in 303ms (Views: 0.2ms | ActiveRecord: 1.6ms)
2019-08-07T21:15:04.170728+00:00 heroku[router]: at=info method=GET path="/api/v1/comics" host=gem-mint-server.herokuapp.com request_id=3afecf82-2c42-4e2c-9f25-cffeb88b5017 fwd="75.18.100.151" dyno=web.1 connect=1ms service=4ms status=401 bytes=736 protocol=https
2019-08-07T21:15:04.170050+00:00 app[web.1]: I, [2019-08-07T21:15:04.169938 #4]  INFO -- : [3afecf82-2c42-4e2c-9f25-cffeb88b5017] Started GET "/api/v1/comics" for 75.18.100.151 at 2019-08-07 21:15:04 +0000
2019-08-07T21:15:04.170902+00:00 app[web.1]: I, [2019-08-07T21:15:04.170835 #4]  INFO -- : [3afecf82-2c42-4e2c-9f25-cffeb88b5017] Processing by Api::V1::ComicsController#index as HTML
2019-08-07T21:15:04.171594+00:00 app[web.1]: I, [2019-08-07T21:15:04.171528 #4]  INFO -- : [3afecf82-2c42-4e2c-9f25-cffeb88b5017] Completed 401 Unauthorized in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms)
2019-08-07T21:15:04.373727+00:00 app[web.1]: I, [2019-08-07T21:15:04.373626 #4]  INFO -- : [82467937-7dbc-4cf2-9cf1-c010f92fad41] Started POST "/refresh" for 75.18.100.151 at 2019-08-07 21:15:04 +0000
2019-08-07T21:15:04.374995+00:00 app[web.1]: I, [2019-08-07T21:15:04.374936 #4]  INFO -- : [82467937-7dbc-4cf2-9cf1-c010f92fad41] Processing by RefreshController#create as HTML
2019-08-07T21:15:04.375091+00:00 app[web.1]: I, [2019-08-07T21:15:04.375032 #4]  INFO -- : [82467937-7dbc-4cf2-9cf1-c010f92fad41]   Parameters: {"refresh"=>{}}
2019-08-07T21:15:04.376098+00:00 app[web.1]: I, [2019-08-07T21:15:04.376018 #4]  INFO -- : [82467937-7dbc-4cf2-9cf1-c010f92fad41] Completed 401 Unauthorized in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms)

0 个答案:

没有答案