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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:15:00