Symfony3 JWT with LexikJWTAuthenticationBundle returns 404 on Preflight OPTIONS
Symfony3 JWT with LexikJWTAuthenticationBundle returns 404 on Preflight OPTIONS
描述:
我正在使用 LexikJWTAuthenticationBundle 并尝试使用从我的 Ionic2 应用程序发送的凭据生成 JWT 令牌。
使用 Curl 和 Postman 可以很好地生成令牌。
curl -X POST http://localhost:8000/api/login_check -d _username=root -d _password=root
但是,Ionic2 在实际发送带有凭据的 POST 请求之前发送预检 OPTIONS 请求。这被 Symfony3 误解并发回 404。
来自 Ionic2 的控制台错误:
OPTIONS http://localhost:8000/api/login_check 404 (Not Found)
XMLHttpRequest cannot load http://localhost:8000/api/login_check.
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8100' is therefore not allowed
access. The response had HTTP status code 404.
0 - {"isTrusted":true}
EXCEPTION: 0 - {"isTrusted":true}
问题:
我必须在我的 Symfony3 应用程序中更改什么(可能是我的 routing.yml 或 security.yml 中的某些内容)才能不发回 404?
代码:
Ionic2 HttpService:
@Injectable()
export class HttpService {
private baseUrl: string = "http://localhost:8000";
constructor(private http: Http){
}
public create<T>(url: string, extractData, data: any = null): Observable<Array<T>>{
let headers = new Headers({ 'Content-Type': 'application/json'});
let options = new RequestOptions({ headers: headers });
return this.http
.post(this.baseUrl + url, data, options)
.map(extractData)
.catch(this.handleError)
}
//More methods here...
}
Symfony routing.yml:
api_login_check:
path: /api/login_check
# This line is something I added to see if OPTIONS would work
# However, it did not work.
methods: [POST, OPTIONS]
类似问题:
Symfony2 JWT Authentication Returning 404 on Preflight
查看 https://github.com/nelmio/NelmioCorsBundle 以找到合适的 header。服务器需要使用适当的 Access-Control-Allow 原始响应 header 进行响应,例如:
Access-Control-Allow-来源:http://localhost:8100
允许请求成功。
关于 CORS 行为的更多信息:https://www.moesif.com/blog/technical/cors/Authoritative-Guide-to-CORS-Cross-Origin-Resource-Sharing-for-REST-APIs/
解释:
因此,在为这个问题绞尽脑汁一整天后,我找到了解决方案。虽然可以合并 NelmioCorsBundle(不确定它是否支持 Symfony3),但我发现绕过 Cors 问题就有点过分了。
在现实世界中 phone 应用程序,不会发送 OPTIONS 预检请求。这只发生在 ionic serve
(根据我的理解)。
我的想法是为 Ionic2 设置一个代理服务器。说起来容易做起来难。似乎有很多关于它的问题。我已经能够让它工作了。
解决方案:
在你的 Ionic2 项目的根目录下应该有一个 ionic.config.json
。你只需要添加几行:
{
"name": "websurgapp",
"app_id": "",
"v2": true,
"typescript": true,
//This is what I added.
"proxies": [{
"path": "*/api", //<- NOTICE THE */ !
"proxyUrl": "http://localhost:8000/api"
}]
}
然后像这样简单地发送请求:
HttpService:
@Injectable()
export class HttpService {http://localhost:8000;
constructor(private http: Http){
}
public create<T>(url: string, data: any = null, contentType: string = 'application/json'): Observable<Array<T>>{
let headers = new Headers({ 'Content-Type': contentType});
let options = new RequestOptions({ headers: headers });
console.log(data);
return this.http
.post(url, data, options)
.map((res:Response)=>res.json())
.catch(this.handleError)
}
}
AuthService:
@Injectable()
export class AuthService {
constructor(public httpService: HttpService) {
console.log('Hello AuthService Provider');
}
private currentUser: User;
public login(credentials): any {
console.log("Login called.");
//TODO: Upgrade symfony to 3.3 to be able to use JSON.
let body = new URLSearchParams();
body.append('_username', credentials._username);
body.append('_password', credentials._password);
let result = this.httpService.create("/api/login_check", body, 'application/x-www-form-urlencoded');
return result;
}
}
请注意,我没有在请求中发送 JSON。该捆绑包目前不支持它。然而,symfony 版本 3.3.(我在 3.1.)确实支持它。
分解:
- 我的 symfony 应用程序在
http://localhost:8000
上运行
- 我的 Ionic 2 应用在
http://localhost:8100
上运行
"path": "*/api"
简单地说,无论我们发出什么请求,其中恰好有一个“/api/”,都将被转换为 proxyUrl。
例如,要生成令牌,我需要将我的凭据发送到 "/api/login_check"
。
我之前试过的:
我之前一直将请求发送到 http://localhost:8000/api/login_check
,这当然会发送预检 OPTIONS 请求,导致一大堆错误。
然后我尝试简单地指定“/api/login_check”,但是 http 请求会添加 "http://localhost:8100"
infront..我的应用程序向自己发送请求..这当然没有用。
解法说明:
随着代理服务器的启动,我简单地向 "/api/login_check"
发送了一个请求,没有任何前端,并且它被作为 POST request
发送到我的 symfony3 应用程序,没有任何 preflight OPTIONS request.
描述:
我正在使用 LexikJWTAuthenticationBundle 并尝试使用从我的 Ionic2 应用程序发送的凭据生成 JWT 令牌。
使用 Curl 和 Postman 可以很好地生成令牌。
curl -X POST http://localhost:8000/api/login_check -d _username=root -d _password=root
但是,Ionic2 在实际发送带有凭据的 POST 请求之前发送预检 OPTIONS 请求。这被 Symfony3 误解并发回 404。
来自 Ionic2 的控制台错误:
OPTIONS http://localhost:8000/api/login_check 404 (Not Found) XMLHttpRequest cannot load http://localhost:8000/api/login_check.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 404.
0 - {"isTrusted":true}
EXCEPTION: 0 - {"isTrusted":true}
问题:
我必须在我的 Symfony3 应用程序中更改什么(可能是我的 routing.yml 或 security.yml 中的某些内容)才能不发回 404?
代码:
Ionic2 HttpService:
@Injectable()
export class HttpService {
private baseUrl: string = "http://localhost:8000";
constructor(private http: Http){
}
public create<T>(url: string, extractData, data: any = null): Observable<Array<T>>{
let headers = new Headers({ 'Content-Type': 'application/json'});
let options = new RequestOptions({ headers: headers });
return this.http
.post(this.baseUrl + url, data, options)
.map(extractData)
.catch(this.handleError)
}
//More methods here...
}
Symfony routing.yml:
api_login_check:
path: /api/login_check
# This line is something I added to see if OPTIONS would work
# However, it did not work.
methods: [POST, OPTIONS]
类似问题:
Symfony2 JWT Authentication Returning 404 on Preflight
查看 https://github.com/nelmio/NelmioCorsBundle 以找到合适的 header。服务器需要使用适当的 Access-Control-Allow 原始响应 header 进行响应,例如:
Access-Control-Allow-来源:http://localhost:8100
允许请求成功。
关于 CORS 行为的更多信息:https://www.moesif.com/blog/technical/cors/Authoritative-Guide-to-CORS-Cross-Origin-Resource-Sharing-for-REST-APIs/
解释:
因此,在为这个问题绞尽脑汁一整天后,我找到了解决方案。虽然可以合并 NelmioCorsBundle(不确定它是否支持 Symfony3),但我发现绕过 Cors 问题就有点过分了。
在现实世界中 phone 应用程序,不会发送 OPTIONS 预检请求。这只发生在 ionic serve
(根据我的理解)。
我的想法是为 Ionic2 设置一个代理服务器。说起来容易做起来难。似乎有很多关于它的问题。我已经能够让它工作了。
解决方案:
在你的 Ionic2 项目的根目录下应该有一个 ionic.config.json
。你只需要添加几行:
{
"name": "websurgapp",
"app_id": "",
"v2": true,
"typescript": true,
//This is what I added.
"proxies": [{
"path": "*/api", //<- NOTICE THE */ !
"proxyUrl": "http://localhost:8000/api"
}]
}
然后像这样简单地发送请求:
HttpService:
@Injectable()
export class HttpService {http://localhost:8000;
constructor(private http: Http){
}
public create<T>(url: string, data: any = null, contentType: string = 'application/json'): Observable<Array<T>>{
let headers = new Headers({ 'Content-Type': contentType});
let options = new RequestOptions({ headers: headers });
console.log(data);
return this.http
.post(url, data, options)
.map((res:Response)=>res.json())
.catch(this.handleError)
}
}
AuthService:
@Injectable()
export class AuthService {
constructor(public httpService: HttpService) {
console.log('Hello AuthService Provider');
}
private currentUser: User;
public login(credentials): any {
console.log("Login called.");
//TODO: Upgrade symfony to 3.3 to be able to use JSON.
let body = new URLSearchParams();
body.append('_username', credentials._username);
body.append('_password', credentials._password);
let result = this.httpService.create("/api/login_check", body, 'application/x-www-form-urlencoded');
return result;
}
}
请注意,我没有在请求中发送 JSON。该捆绑包目前不支持它。然而,symfony 版本 3.3.(我在 3.1.)确实支持它。
分解:
- 我的 symfony 应用程序在
http://localhost:8000
上运行
- 我的 Ionic 2 应用在
http://localhost:8100
上运行
"path": "*/api"
简单地说,无论我们发出什么请求,其中恰好有一个“/api/”,都将被转换为 proxyUrl。
例如,要生成令牌,我需要将我的凭据发送到 "/api/login_check"
。
我之前试过的:
我之前一直将请求发送到 http://localhost:8000/api/login_check
,这当然会发送预检 OPTIONS 请求,导致一大堆错误。
然后我尝试简单地指定“/api/login_check”,但是 http 请求会添加 "http://localhost:8100"
infront..我的应用程序向自己发送请求..这当然没有用。
解法说明:
随着代理服务器的启动,我简单地向 "/api/login_check"
发送了一个请求,没有任何前端,并且它被作为 POST request
发送到我的 symfony3 应用程序,没有任何 preflight OPTIONS request.