Angular5通过JWT对接API认证失败求助:Postman/Curl正常但报401
我明白你的问题了!问题出在Angular发送请求的数据格式上,和Postman/curl的请求不匹配。
问题根源
你用Postman和curl发送的是表单格式的请求体(curl的-d参数默认使用application/x-www-form-urlencoded,Postman则自动用了multipart/form-data),但你的Angular代码直接把JSON对象作为请求体发送——HttpClient默认会将这个对象序列化成application/json格式的字符串,同时设置Content-Type: application/json请求头。
而后端的/api/login_check接口(看起来像是Symfony Security的默认登录路由)期望的是表单格式的参数,所以它无法从JSON请求体中解析出_username和_password,自然返回401“无效凭证”错误。你之前尝试添加contentType: 'application/x-www-form-urlencoded'但没成功,是因为只改了请求头,没修改请求体的格式,头和内容不匹配,后端还是解析不了。
解决方案
这里有两种可行的方法,任选其一即可:
方法1:发送application/x-www-form-urlencoded格式的请求
用HttpParams构建表单参数,同时设置正确的请求头:
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; const API_URL = 'http://localhost/api'; @Injectable() export class SecurityService { constructor(private http: HttpClient) { } login(username: string, password: string) { const url = `${API_URL}/login_check`; // 用HttpParams构建表单参数 const body = new HttpParams() .set('_username', username) .set('_password', password); // 设置正确的Content-Type const headers = new HttpHeaders() .set('Content-Type', 'application/x-www-form-urlencoded'); return this.http.post(url, body.toString(), { headers }) .subscribe( (response) => { console.log('登录成功:', response); }, (error) => { console.error('登录失败:', error); } ); } }
方法2:发送multipart/form-data格式的请求(和Postman一致)
用FormData对象构建请求体,它会自动设置正确的Content-Type请求头:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; const API_URL = 'http://localhost/api'; @Injectable() export class SecurityService { constructor(private http: HttpClient) { } login(username: string, password: string) { const url = `${API_URL}/login_check`; // 用FormData构建表单数据 const formData = new FormData(); formData.append('_username', username); formData.append('_password', password); return this.http.post(url, formData) .subscribe( (response) => { console.log('登录成功:', response); }, (error) => { console.error('登录失败:', error); } ); } }
额外提示
如果你的后端是Symfony,建议优先用方法1,因为application/x-www-form-urlencoded比multipart/form-data更轻量,适合简单的表单提交场景。
内容的提问来源于stack exchange,提问作者MatMouth

