【问题标题】:Symfony3 JWT with LexikJWTAuthenticationBundle returns 404 on Preflight OPTIONS带有 LexikJWTAuthenticationBundle 的 Symfony3 JWT 在 Preflight OPTIONS 上返回 404
【发布时间】:2017-06-05 12:56:37
【问题描述】:

说明:

我正在使用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 的控制台错误:

选项http://localhost:8000/api/login_check 404(未找到) XMLHttpRequest 无法加载http://localhost:8000/api/login_check

对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://localhost:8100” 使用权。响应的 HTTP 状态代码为 404。

0 - {"isTrusted":true}

例外: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

【问题讨论】:

标签: typescript cors ionic2 symfony lexikjwtauthbundle


【解决方案1】:

查看https://github.com/nelmio/NelmioCorsBundle 以查看相应的标题。服务器需要使用适当的 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,但我发现添加一个包来处理 Cors 有点过头了。从我从问题中可以看出,它也不支持 symfony3。它可能确实有效。
【解决方案2】:

解释:

因此,经过一整天的思考,我找到了解决方案。虽然可以合并 NelmioCorsBundle(不确定它是否支持 Symfony3),但我觉得绕过 Cors 问题有点矫枉过正。

在现实世界的电话应用程序中,不会发送 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.)确实支持它。

分解:

  1. 我的 symfony 应用程序在 http://localhost:8000 上运行
  2. 我的 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.

【讨论】:

    猜你喜欢
    • 2012-12-22
    • 2012-12-31
    • 2019-01-19
    • 1970-01-01
    • 2019-01-05
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多