You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular5通过JWT对接API认证失败求助:Postman/Curl正常但报401

解决Angular调用JWT登录API返回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:32:00