Get请求成功后,Angular 9首次PUT正常,后续PUT报302/503错误的原因
ASP.NET Core 2.2 API + Angular 9:首次PUT请求正常,后续PUT返回302/503的原因及解决办法
问题场景
在ASP.NET Core 2.2 API控制器中,Get请求执行成功后,Angular 9的首次PUT请求能够正常完成,但后续发起的PUT请求却返回HTTP 302或503错误。
问题根源及解决要点
- [Authorize]属性顺序错误:在需要授权的数据访问Action方法中,
[Authorize]属性必须放在Http动词属性(如[HttpPut])之前,否则ASP.NET Core授权中间件无法正确拦截请求,导致后续请求出现授权异常。 - 状态码返回不规范:JWT令牌验证与模型状态校验逻辑存在缺陷,未按HTTP标准返回对应状态码:无效模型状态应返回400(BadRequest),无效JWT或会话超时需返回401(未授权)。错误的状态码会触发中间件跳转逻辑(302)或导致服务端资源异常(503)。
- 会话与授权流程不完整:需正确使用dbo.Session存储会话数据,所有需要授权的HTTP请求必须携带JWT头,且在Session控制器中完成JWT令牌的验证与授权逻辑,避免会话状态不一致引发后续请求失败。
代码示例
Angular 9 客户端代码
import { Injectable } from "@angular/core"; import { HttpClient, HttpHeaders } from "@angular/common/http"; import { Member } from "./member.model"; import { DatasourcesService } from "./datasources.service"; const sessionUrl = "/api/session"; // 基于"购物车"模型扩展的会话数据模型 export class ContactInfo { selections: MembersInfoSelection[] = []; itemCount: number = 0; constructor(private http: HttpClient, private authBearer: DatasourcesService) { this.selections = []; } storeSessionData<T>(dataType: string, data: T) { let myHeaders = new HttpHeaders(); // 根据是否存在JWT令牌设置请求头 if (this.authBearer.JWTauthcookie == null) { myHeaders = myHeaders.set("Access-Key", "<secret>"); } else { myHeaders = myHeaders.set("Authorization", `Bearer ${this.authBearer.JWTauthcookie}`); } myHeaders = myHeaders.set("Application-Names", ["ClientApp", "My-App"]); return this.http.post(`${sessionUrl}/${dataType}`, data, { headers: myHeaders }).subscribe(response => { }); } addMemberInfo(member: Member) { let selection = this.selections .find(mis => mis.memberid == member.memberID); if (selection) { selection.quantity++; } else { this.selections.push(new MembersInfoSelection( this, member.memberID, member.last_Name, member.first_Name, member.midInit, member.cell_Phone, member.email_Address )); } this.update(); } update(storeData: boolean = true) { if (storeData) { this.storeSessionData("contactinfo", this.selections.map(s => { return { memberid: s.memberid, lastname: s.lastname, firstname: s.firstname, midinit: s.midinit, cellphone: s.cellphone, emailaddress: s.emailaddress, quantity: s.quantity } })); } } } // 会话数据选择项模型 export class MembersInfoSelection { constructor( public contactinfo: ContactInfo, public memberid?: number, public lastname?: string, public firstname?: string, public midinit?: string, public cellphone?: string, public emailaddress?: string, public quantity?: number ) { } }
ASP.NET Core 2.2 服务端控制器代码
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using ServerApp.Models; using ServerApp.Infrastructure; using Microsoft.AspNetCore.Authorization; namespace ServerApp.Controllers { [Route("/api/session")] [AllowAnonymous] [ApiController] public class SessionValuesController : Controller { private readonly Jwt_GenerateToken _valToken = new Jwt_GenerateToken(); [HttpGet("contactinfo")] public IActionResult GetContactInfo() { return Ok(HttpContext.Session.GetString("contactinfo")); } // 注意:[Authorize]属性必须放在[HttpPost]之前 [Authorize(Roles = "Admin,Super,User")] [HttpPost("contactinfo")] public IActionResult StoreContactInfo([FromBody] SessionInfo[] contacts) { // 提取并验证JWT令牌 if (!Request.Headers.TryGetValue("Authorization", out var bearerToken)) { return Unauthorized(); } if (!bearerToken.ToString().StartsWith("Bearer ")) { return Unauthorized(); } var token = bearerToken.ToString().Substring(7); if (!_valToken.ValidateCurrentToken(token)) { return Unauthorized(); } // 校验模型状态 if (!ModelState.IsValid) { return BadRequest(ModelState); } // 存储会话数据到dbo.Session对应的Session存储 var jsonData = JsonConvert.SerializeObject(contacts); HttpContext.Session.SetString("contactinfo", jsonData); return Ok(); } } }
内容的提问来源于stack exchange,提问作者Cwinds
相关产品推荐
相关产品推荐

