问题
I am new to react, and mostly to javascript. I am using react for a web app hosted on localhost:3000 with node.js and symfony 2.8 for my back end, hosted on localhost:80 with apache, that exposes an api secured with lexik and fos user. Before securing the api, everything works fine. After securing the api, I get a 401 error when using fetch as follow:
let myToken = localStorage.getItem('auth_token') //token properly retrieved
let myHeaders = new Headers();
myHeaders.append("Authorization", myToken)
return fetch(
pathToMyResource,
{
method: "post",
headers: myHeaders
}
).then(do stuff with the answer)
This gives me the following error in the headers of the answer to the preflight request:
Request URL:http://127.0.0.1/edsa-food_app_symfony_2.8/api/site/1/get
Request Method:OPTIONS
Status Code:401 Unauthorized
Remote Address:127.0.0.1:80
Referrer Policy:no-referrer-when-downgrade
And the response:
{"code":401,"message":"JWT Token not found"}
I also checked, just because I don't really understand how this is supposed to work, with
credentials: 'include'
And
mode: 'no-cors'
But wasn't more successful.
When I build and send this same request using php from localhost:8000, it works perfectly. I use the following code:
$url = pathToMyResource
$options = array(
'http' => array(
'header' => "Authorization: Bearer $token"
'method' => 'POST',
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
var_dump($result);
If I understand well it cannot be the apache error described in Lexik JWT Token not found: the default .htaccess at the root of any symfony 2.8 project includes:
RewriteEngine On
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
I checked and mod_rewrite is enabled.
Below are the headers as reported in Chrome:
**General**
Request URL:http://127.0.0.1/edsa-food_app_symfony_2.8/api/site/1/get
Request Method:OPTIONS
Status Code:401 Unauthorized
Remote Address:127.0.0.1:80
Referrer Policy:no-referrer-when-downgrade
**Response Headers**
view source
Access-Control-Allow-Origin:*
Cache-Control:no-cache
Connection:Keep-Alive
Content-Length:44
Content-Type:application/json
Date:Tue, 08 Aug 2017 01:05:20 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.18 (Win32) PHP/5.6.19
WWW-Authenticate:Bearer
X-Powered-By:PHP/5.6.19
**Request Headers**
view source
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-GB,en;q=0.8,en-US;q=0.6,fr;q=0.4,zh-CN;q=0.2,zh;q=0.2,it;q=0.2
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST
Connection:keep-alive
Host:127.0.0.1
Origin:http://localhost:3000
Referer:http://localhost:3000/service-worker.js
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
And for the POST request itself:
**General**
Request URL:http://127.0.0.1/edsa-food_app_symfony_2.8/api/site/1/get
Referrer Policy:no-referrer-when-downgrade
**Request Headers**
Provisional headers are shown
authorization:Bearer eyJhbGciOiJSUzI1NiJ9.eyJyb2xlcyI6WyJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJhbnRvaW5lIiwiaWF0IjoxNTAyMTM4ODUwLCJleHAiOjE1MDIyMjUyNTB9.wpWZZLf5wWjrU0-eAQUR0XiDTvf1jRtiJuGIHoYm7Yo4lGhOn-_bYuJIdv71ZUiuYfaaMxOW4xzXN3JjB9KfrWmXD4jqI6CnHFYZISGlYvAGJayD_z8CMIEdvrMXrbb6_nEc0CaB68BOf7wqJyoNatFKlepwmCHevsRtTIbhc_GviQf_U_Fw30ShtogIJBLqmVD4ex-j0_9QbblAIqNhc8c0thEFYtN7FVepLehCzBNCTNL8l-mxYEFTrUYLKwSt4lRahgTsv4Ozhxl300xz7BbdQEr3ph2i4ssVcvokpEO2C07QicWSwXFx1Vx-2a6XbkoeorTz_P7WstBzinMdv0etlIz2VYN_oUmHaxDu9jlsu90nZlL2Ea7Ak7dSJaNYzmB11yga_OSiWMpzWTjaqP3MLJuS1O5keHMbliERgnBJM_rsMZ-mkVSM8j4t31L1QJCfP0RW-Vfj3biYR1uYNfXwbbdqmIpn6b39qOCY9l4F99dK6R-PKq5ZeBHEfy-OpN39NFmaMQQX5gYCQ3TzVdeou6-hjpqRnNl8dc0HYzAl3fbU102JMefZNvCsIdcI6WDCiyWZO9Viy-z9REAVF4Pr9bLFpc-Q6Lqdj32lt1-yy6i75IOavrPqRilhRh2z_V7rP_DqahrLhFSDPPVg_gcqb8n31_6q3wtyzx16aJ4
Origin:http://localhost:3000
Referer:http://localhost:3000/restaurant
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
I am lost.
回答1:
You need to configure your backend so that it responds to the preflight with a 200 or 204.
You may be able to handle that at the Apache level by adding your your Apache config this:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
But if that doesn’t fix is then you gonna need to dig further and figure out what part of your backend system is causing authentication to be required for OPTIONS requests.
The reason is because what’s happening here is this:
- Your code tells your browser it wants to send a request with the
Authorizationheader. - Your browser says, OK, requests with the
Authorizationheader require me to do a CORS preflightOPTIONSto make sure the server allows requests with that header. - Your browser sends the
OPTIONSrequest to the server without theAuthorizationheader—because the whole purpose of theOPTIONScheck is to see if it’s OK to send that. - The server sees the
OPTIONSrequest but instead of responding to it in a way that indicates it allowsAuthorizationin requests, it rejects it with a 401 since it lacks that header. - Your browser expects a 200 or 204 response for the CORS preflight but instead gets that 401 response. So your browser stops right there and never tries the
POSTrequest from your code.
来源:https://stackoverflow.com/questions/45557941/401-error-jwt-token-not-found-using-fetch