使用 React 时 rails api-only 应用程序出现 401 未经授权的错误
401 Unauthorized error in rails api-only app when using React
我正在尝试将 rails api-ony 应用程序用作 back-end 并将 React js 用作 front-end。我正在使用 axios 发送/接收请求。最初我什至无法登录,然后在多次谷歌搜索后我发现 this gem 它是关于 CORS,它解决了我的 POST 请求错误。
当我在 rails 应用程序中执行 POST 请求并且我在 return 中获得令牌时,我能够成功登录(这与 POSTMAN 应用程序一起工作正常)。现在,当我执行 GET 请求并使用 React 应用程序将该令牌作为 Header 传递时,它一直给我 401 Unauthorized error
,然后在多次谷歌搜索后我再次看到 this SO post。它没有解决问题。我错过了什么?请说明这个问题的原因。
这是application_controller.rb:
class ApplicationController < ActionController::API
include ActionController::MimeResponds
before_action :authenticate_request, :current_user, :cors_preflight_check
attr_reader :current_user
#before_filter :current_user, :cors_preflight_check
after_action :cors_set_access_control_headers
# For all responses in this controller, return the CORS access control headers.
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
headers['Access-Control-Max-Age'] = "1728000"
end
# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
if request.method == :options
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
require 'date'
require 'json'
require 'groupdate'
@@PRESENT_DATE=Date.parse('2016-12-31T00:00:00.000Z')
@@MONTHLY_SELECTOR="SELECT CONCAT(MONTHNAME(invoiceDate),' - ',YEAR(invoiceDate)), SUM(invoiceAmt) FROM invoices GROUP BY YEAR(invoiceDate), MONTH(invoiceDate)"
@@QUARTERLY_SELECTOR="SELECT SUM(invoiceAmt) AS invoiceTotal, CONCAT('Q',QUARTER(invoiceDate), '(', YEAR(invoiceDate), ')') FROM invoices GROUP BY YEAR(invoiceDate), QUARTER(invoiceDate) ORDER BY YEAR(invoiceDate), QUARTER(invoiceDate)"
@@YEARLY_SELECTOR="SELECT SUM(invoiceAmt) AS invoiceTotal, YEAR(invoiceDate) AS Year FROM invoices GROUP BY YEAR(invoiceDate) ORDER BY YEAR(invoiceDate)"
private
def authenticate_request
@current_user = AuthorizeApiRequest.call(request.headers).result
render json: { error: 'Not Authorized' }, status: 401 unless @current_user
end
end
在我的反应应用程序中我有这个:
import React, { Component } from 'react';
import '../App.css';
var axios = require('axios');
class Login extends Component {
constructor(props){
super(props);
//this.state = {isToggleOn: true};
this.loadDashboard = this.loadDashboard.bind(this);
this.handleOnSubmit = this.handleOnSubmit.bind(this);
}
loadDashboard(token){
axios({
method:'get',
url:'http://localhost:3000/api/dashboard',
Authorization: {
Authorization: token,
},
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log("Error in loading Dashboard "+error.response.status);
});
}
handleOnSubmit = () => {
console.log("submittwed");
axios({
method:'post',
url:'http://localhost:3000/authenticate',
data: {
email: 'test@mail.com',
password: 'apple'
},
})
.then((response) => {
var token = response.data.auth_token;
console.log(token);
this.loadDashboard(token);
})
.catch(function (error) {
console.log("Error in login "+error);
});
}
render() {
return (
<div>
Username: <input type="email" name="fname" /><br />
Password: <input type="password" name="lname" /><br />
<button onClick={this.handleOnSubmit}>LOG IN</button>
</div>
);
}
}
export default Login;
完整 header 响应:
Request URL:http://localhost:3000/api/dashboard
Request Method:GET
Status Code:401 Unauthorized
Remote Address:127.0.0.1:3000
Referrer Policy:no-referrer-when-downgrade
Response Headers
view source
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:
Access-Control-Max-Age:1728000
Cache-Control:no-cache
Content-Type:application/json; charset=utf-8
Transfer-Encoding:chunked
Vary:Origin
X-Request-Id:f78a4c29-ef9a-446c-8771-9e2b70d41757
X-Runtime:0.045998
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:3001
Referer:http://localhost:3001/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Rails版本:Rails5.1.3
- 有没有其他人遇到过类似的事情??
- 我该如何解决这个问题?
- 有没有少messy/better的办法?
请帮我解决这个问题。
您缺少发送至 api 呼叫的 headers
键。
axios({
method:'get',
url:'http://localhost:3000/api/dashboard',
headers: {
Authorization: `Bearer ${token}`,
},
})
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log("Error in loading Dashboard "+error.response.status)
})
我正在尝试将 rails api-ony 应用程序用作 back-end 并将 React js 用作 front-end。我正在使用 axios 发送/接收请求。最初我什至无法登录,然后在多次谷歌搜索后我发现 this gem 它是关于 CORS,它解决了我的 POST 请求错误。
当我在 rails 应用程序中执行 POST 请求并且我在 return 中获得令牌时,我能够成功登录(这与 POSTMAN 应用程序一起工作正常)。现在,当我执行 GET 请求并使用 React 应用程序将该令牌作为 Header 传递时,它一直给我 401 Unauthorized error
,然后在多次谷歌搜索后我再次看到 this SO post。它没有解决问题。我错过了什么?请说明这个问题的原因。
这是application_controller.rb:
class ApplicationController < ActionController::API
include ActionController::MimeResponds
before_action :authenticate_request, :current_user, :cors_preflight_check
attr_reader :current_user
#before_filter :current_user, :cors_preflight_check
after_action :cors_set_access_control_headers
# For all responses in this controller, return the CORS access control headers.
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
headers['Access-Control-Max-Age'] = "1728000"
end
# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
if request.method == :options
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
require 'date'
require 'json'
require 'groupdate'
@@PRESENT_DATE=Date.parse('2016-12-31T00:00:00.000Z')
@@MONTHLY_SELECTOR="SELECT CONCAT(MONTHNAME(invoiceDate),' - ',YEAR(invoiceDate)), SUM(invoiceAmt) FROM invoices GROUP BY YEAR(invoiceDate), MONTH(invoiceDate)"
@@QUARTERLY_SELECTOR="SELECT SUM(invoiceAmt) AS invoiceTotal, CONCAT('Q',QUARTER(invoiceDate), '(', YEAR(invoiceDate), ')') FROM invoices GROUP BY YEAR(invoiceDate), QUARTER(invoiceDate) ORDER BY YEAR(invoiceDate), QUARTER(invoiceDate)"
@@YEARLY_SELECTOR="SELECT SUM(invoiceAmt) AS invoiceTotal, YEAR(invoiceDate) AS Year FROM invoices GROUP BY YEAR(invoiceDate) ORDER BY YEAR(invoiceDate)"
private
def authenticate_request
@current_user = AuthorizeApiRequest.call(request.headers).result
render json: { error: 'Not Authorized' }, status: 401 unless @current_user
end
end
在我的反应应用程序中我有这个:
import React, { Component } from 'react';
import '../App.css';
var axios = require('axios');
class Login extends Component {
constructor(props){
super(props);
//this.state = {isToggleOn: true};
this.loadDashboard = this.loadDashboard.bind(this);
this.handleOnSubmit = this.handleOnSubmit.bind(this);
}
loadDashboard(token){
axios({
method:'get',
url:'http://localhost:3000/api/dashboard',
Authorization: {
Authorization: token,
},
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log("Error in loading Dashboard "+error.response.status);
});
}
handleOnSubmit = () => {
console.log("submittwed");
axios({
method:'post',
url:'http://localhost:3000/authenticate',
data: {
email: 'test@mail.com',
password: 'apple'
},
})
.then((response) => {
var token = response.data.auth_token;
console.log(token);
this.loadDashboard(token);
})
.catch(function (error) {
console.log("Error in login "+error);
});
}
render() {
return (
<div>
Username: <input type="email" name="fname" /><br />
Password: <input type="password" name="lname" /><br />
<button onClick={this.handleOnSubmit}>LOG IN</button>
</div>
);
}
}
export default Login;
完整 header 响应:
Request URL:http://localhost:3000/api/dashboard
Request Method:GET
Status Code:401 Unauthorized
Remote Address:127.0.0.1:3000
Referrer Policy:no-referrer-when-downgrade
Response Headers
view source
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:
Access-Control-Max-Age:1728000
Cache-Control:no-cache
Content-Type:application/json; charset=utf-8
Transfer-Encoding:chunked
Vary:Origin
X-Request-Id:f78a4c29-ef9a-446c-8771-9e2b70d41757
X-Runtime:0.045998
Request Headers
view source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:3001
Referer:http://localhost:3001/
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Rails版本:Rails5.1.3
- 有没有其他人遇到过类似的事情??
- 我该如何解决这个问题?
- 有没有少messy/better的办法?
请帮我解决这个问题。
您缺少发送至 api 呼叫的 headers
键。
axios({
method:'get',
url:'http://localhost:3000/api/dashboard',
headers: {
Authorization: `Bearer ${token}`,
},
})
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log("Error in loading Dashboard "+error.response.status)
})