GraphQl+ jwt auth+ Axios IS不起作用并抛出错误:错误:访问被拒绝!您需要被授权执行此操作
我对GraphQL有一个后端,并且使用JWT Auth对其进行保护。 当我使用失眠发送GraphQL请求时,它可以正常工作! 但是,当我使用Axios发送时,它不起作用。我正在使用React本机
考虑考虑:
- JWT未过期,因为我可以复制/粘贴它并使用失眠症,
- 我可以使用其他方法进行相同的请求,例如:失眠,使用其他脚本
- API_URI直接调用: http:// localhost:3000/development/,
- Axios版本(APP):0.27.2
- GraphQl版本(APP):15.5.1
- GraphQl-TAG版本(APP):2.12.5
/* eslint-disable no-console */
import axios, { AxiosRequestConfig } from 'axios';
import config from '../../config';
import store from '../stores';
const api = axios.create({
baseURL: config.API_URI,
});
api.interceptors.request.use((config: AxiosRequestConfig) => {
const { token, pushNotificationToken } = store.getState().user;
config.headers.Authorization = `Bearer ${token}`;
config.headers.pushnotificationtoken = pushNotificationToken || '';
return config;
});
api.interceptors.request.use(request => {
console.log(
'\n======================= STARTING REQUEST ===========================\n',
);
console.log(JSON.stringify(request, null, 2));
console.log(
'\n======================= ENDING REQUEST ===========================\n',
);
return request;
});
api.interceptors.response.use(response => {
console.log(
'\n======================= STARTING RESPONSE ===========================\n',
);
console.log(JSON.stringify(response, null, 2));
console.log(
'\n======================= ENDING RESPONSE ===========================\n',
);
return response;
});
export async function apiRequest<ResponseType>(
body: any,
): Promise<ResponseType> {
const response = await api.post('graphql', body);
const { data } = response;
if (data.errors && data.errors.length > 0) {
throw new Error(data.errors[0].message || 'Ops! An error has occurred.');
}
return data.data;
}
export default api;
使用AXIOS来自后端的响应:使用Axios:使用
{
"data": {
"errors": [{
"message": "Access Denied",
"locations": [{
"line": 2,
"column": 3
}],
"path": [
"getAllOrders"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Access denied! You need to be authorized to perform this action!",
" at /home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/helpers/auth-middleware.js:13:1",
" at dispatchHandler (/home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/resolvers/helpers.js:82:1)"
]
}
}
}],
"data": null
},
"status": 200,
"headers": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"date": "Tue, 14 Jun 2022 15:32:37 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"keep-alive": "timeout=5"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {
"FormData": null
},
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"Authorization": "Bearer + MY JWT TOKEN GOES HERE",
"pushnotificationtoken": ""
},
"baseURL": "http://10.0.2.2:3000/development/",
"method": "post",
"url": "graphql",
"data": "{\"query\":\"query getAllOrders {\\n getAllOrders {\\n id\\n status\\n table\\n items {\\n id\\n description\\n quantity\\n priceCents\\n }\\n totalOrderPriceCents\\n createdAt\\n }\\n}\\n\"}"
},
"request": {
"UNSENT": 0,
"OPENED": 1,
"HEADERS_RECEIVED": 2,
"LOADING": 3,
"DONE": 4,
"readyState": 4,
"status": 200,
"timeout": 0,
"withCredentials": true,
"upload": {},
"_aborted": false,
"_hasError": false,
"_method": "POST",
"_perfKey": "network_XMLHttpRequest_http://10.0.2.2:3000/development/graphql",
"_response": "{\"errors\":[{\"message\":\"Acesso não autorizado\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"getAllOrders\"],\"extensions\":{\"code\":\"INTERNAL_SERVER_ERROR\",\"exception\":{\"stacktrace\":[\"Error: Access denied! You need to be authorized to perform this action!\",\" at /home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/helpers/auth-middleware.js:13:1\",\" at dispatchHandler (/home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/resolvers/helpers.js:82:1)\"]}}}],\"data\":null}\n",
"_url": "http://10.0.2.2:3000/development/graphql",
"_timedOut": false,
"_trackingName": "unknown",
"_incrementalEvents": false,
"responseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"Connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"Date": "Tue, 14 Jun 2022 15:32:37 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"Keep-Alive": "timeout=5"
},
"_requestId": null,
"_headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"authorization": "Bearer + jwt goes here",
"pushnotificationtoken": ""
},
"_responseType": "",
"_sent": true,
"_lowerCaseResponseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"date": "Tue, 14 Jun 2022 15:32:37 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"keep-alive": "timeout=5"
},
"_subscriptions": [],
"responseURL": "http://10.0.2.2:3000/development/graphql"
}
}
相同的请求使用相同的请求失眠:
失眠时间表:
console.log(wendesp.request):
{
"UNSENT": 0,
"OPENED": 1,
"HEADERS_RECEIVED": 2,
"LOADING": 3,
"DONE": 4,
"readyState": 4,
"status": 200,
"timeout": 0,
"withCredentials": true,
"upload": {},
"_aborted": false,
"_hasError": false,
"_method": "POST",
"_perfKey": "network_XMLHttpRequest_http://10.0.2.2:3000/development/graphql",
"_response": "{\"errors\":[{\"message\":\"Acesso não autorizado\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"getAllOrders\"],\"extensions\":{\"code\":\"INTERNAL_SERVER_ERROR\",\"exception\":{\"stacktrace\":[\"Error: Access denied! You need to be authorized to perform this action!\",\" at /home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/helpers/auth-middleware.js:13:1\",\" at dispatchHandler (/home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/resolvers/helpers.js:82:1)\"]}}}],\"data\":null}\n",
"_url": "http://10.0.2.2:3000/development/graphql",
"_timedOut": false,
"_trackingName": "unknown",
"_incrementalEvents": false,
"responseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"Connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"Date": "Tue, 14 Jun 2022 17:42:39 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"Keep-Alive": "timeout=5"
},
"_requestId": null,
"_headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"authorization": "Bearer eyJ........",
"pushnotificationtoken": ""
},
"_responseType": "",
"_sent": true,
"_lowerCaseResponseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"date": "Tue, 14 Jun 2022 17:42:39 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"keep-alive": "timeout=5"
},
"_subscriptions": [],
"responseURL": "http://10.0.2.2:3000/development/graphql"
}
I Have a backend with GraphQL and I use JWT Auth to protect it.
When I sent my GraphQL request using Insomnia, it works properly!
However when I sent using Axios it doesn't work. I'm Using React Native
Some points to consider:
- Jwt isn't expired, because I can copy/paste it and use using Insomnia
- I can do the same request using other methods, for example: Insomnia, direct call using other scripts
- API_URI: http://localhost:3000/development/,
- Axios Version (app): 0.27.2
- graphql version (app): 15.5.1
- graphql-tag version (app): 2.12.5
/* eslint-disable no-console */
import axios, { AxiosRequestConfig } from 'axios';
import config from '../../config';
import store from '../stores';
const api = axios.create({
baseURL: config.API_URI,
});
api.interceptors.request.use((config: AxiosRequestConfig) => {
const { token, pushNotificationToken } = store.getState().user;
config.headers.Authorization = `Bearer ${token}`;
config.headers.pushnotificationtoken = pushNotificationToken || '';
return config;
});
api.interceptors.request.use(request => {
console.log(
'\n======================= STARTING REQUEST ===========================\n',
);
console.log(JSON.stringify(request, null, 2));
console.log(
'\n======================= ENDING REQUEST ===========================\n',
);
return request;
});
api.interceptors.response.use(response => {
console.log(
'\n======================= STARTING RESPONSE ===========================\n',
);
console.log(JSON.stringify(response, null, 2));
console.log(
'\n======================= ENDING RESPONSE ===========================\n',
);
return response;
});
export async function apiRequest<ResponseType>(
body: any,
): Promise<ResponseType> {
const response = await api.post('graphql', body);
const { data } = response;
if (data.errors && data.errors.length > 0) {
throw new Error(data.errors[0].message || 'Ops! An error has occurred.');
}
return data.data;
}
export default api;
Response from backend Using Axios:
{
"data": {
"errors": [{
"message": "Access Denied",
"locations": [{
"line": 2,
"column": 3
}],
"path": [
"getAllOrders"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Access denied! You need to be authorized to perform this action!",
" at /home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/helpers/auth-middleware.js:13:1",
" at dispatchHandler (/home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/resolvers/helpers.js:82:1)"
]
}
}
}],
"data": null
},
"status": 200,
"headers": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"date": "Tue, 14 Jun 2022 15:32:37 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"keep-alive": "timeout=5"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {
"FormData": null
},
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"Authorization": "Bearer + MY JWT TOKEN GOES HERE",
"pushnotificationtoken": ""
},
"baseURL": "http://10.0.2.2:3000/development/",
"method": "post",
"url": "graphql",
"data": "{\"query\":\"query getAllOrders {\\n getAllOrders {\\n id\\n status\\n table\\n items {\\n id\\n description\\n quantity\\n priceCents\\n }\\n totalOrderPriceCents\\n createdAt\\n }\\n}\\n\"}"
},
"request": {
"UNSENT": 0,
"OPENED": 1,
"HEADERS_RECEIVED": 2,
"LOADING": 3,
"DONE": 4,
"readyState": 4,
"status": 200,
"timeout": 0,
"withCredentials": true,
"upload": {},
"_aborted": false,
"_hasError": false,
"_method": "POST",
"_perfKey": "network_XMLHttpRequest_http://10.0.2.2:3000/development/graphql",
"_response": "{\"errors\":[{\"message\":\"Acesso não autorizado\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"getAllOrders\"],\"extensions\":{\"code\":\"INTERNAL_SERVER_ERROR\",\"exception\":{\"stacktrace\":[\"Error: Access denied! You need to be authorized to perform this action!\",\" at /home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/helpers/auth-middleware.js:13:1\",\" at dispatchHandler (/home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/resolvers/helpers.js:82:1)\"]}}}],\"data\":null}\n",
"_url": "http://10.0.2.2:3000/development/graphql",
"_timedOut": false,
"_trackingName": "unknown",
"_incrementalEvents": false,
"responseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"Connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"Date": "Tue, 14 Jun 2022 15:32:37 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"Keep-Alive": "timeout=5"
},
"_requestId": null,
"_headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"authorization": "Bearer + jwt goes here",
"pushnotificationtoken": ""
},
"_responseType": "",
"_sent": true,
"_lowerCaseResponseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"date": "Tue, 14 Jun 2022 15:32:37 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"keep-alive": "timeout=5"
},
"_subscriptions": [],
"responseURL": "http://10.0.2.2:3000/development/graphql"
}
}
The same request using Insomnia:
Insomnia Timeline:
console.log(response.request):
{
"UNSENT": 0,
"OPENED": 1,
"HEADERS_RECEIVED": 2,
"LOADING": 3,
"DONE": 4,
"readyState": 4,
"status": 200,
"timeout": 0,
"withCredentials": true,
"upload": {},
"_aborted": false,
"_hasError": false,
"_method": "POST",
"_perfKey": "network_XMLHttpRequest_http://10.0.2.2:3000/development/graphql",
"_response": "{\"errors\":[{\"message\":\"Acesso não autorizado\",\"locations\":[{\"line\":2,\"column\":3}],\"path\":[\"getAllOrders\"],\"extensions\":{\"code\":\"INTERNAL_SERVER_ERROR\",\"exception\":{\"stacktrace\":[\"Error: Access denied! You need to be authorized to perform this action!\",\" at /home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/helpers/auth-middleware.js:13:1\",\" at dispatchHandler (/home/agostinho/Documents/MY-MOBILE-PROJECT/v1/MY-MOBILE-PROJECT-back-end-2020/.webpack/service/src/webpack:/node_modules/type-graphql/dist/resolvers/helpers.js:82:1)\"]}}}],\"data\":null}\n",
"_url": "http://10.0.2.2:3000/development/graphql",
"_timedOut": false,
"_trackingName": "unknown",
"_incrementalEvents": false,
"responseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"Connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"Date": "Tue, 14 Jun 2022 17:42:39 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"Keep-Alive": "timeout=5"
},
"_requestId": null,
"_headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"authorization": "Bearer eyJ........",
"pushnotificationtoken": ""
},
"_responseType": "",
"_sent": true,
"_lowerCaseResponseHeaders": {
"access-control-expose-headers": "WWW-Authenticate,Server-Authorization",
"connection": "keep-alive",
"vary": "origin",
"access-control-allow-credentials": "true",
"content-length": "601",
"date": "Tue, 14 Jun 2022 17:42:39 GMT",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"keep-alive": "timeout=5"
},
"_subscriptions": [],
"responseURL": "http://10.0.2.2:3000/development/graphql"
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我发现了错误。这是我授权者背景下的行为!
失眠症正在用
以
a
为大写,但是,Axios用授权
, a a 作为小写。我需要调试后端,因此我使用以下内容来处理:
const授权= ctx.event.headers.authorization || ctx.event.headers.authorization
因此,我的授权者上下文将在两种情况下处理。
最终代码:
I found the error. It was a behavior at my authorizer context!
The Insomnia was sending
Authorization
with theA
as Uppercase, however, axios was sendingauthorization
with thea
as lowercase.I needed to debug my backend, so I use the following to handle with that:
const Authorization = ctx.event.headers.Authorization || ctx.event.headers.authorization
Thus, my authorizer context will handle with two situations.
The final code: