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

JQuery请求REST服务返回401 Unauthorized问题求助

解决AJAX调用返回401但直接访问API正常的问题

我最近给学校开发了一款小型音频应用,部署在Heroku上,结果碰到个棘手的问题:用jQuery写的getPlaylist函数调用API获取歌曲时,一直返回401未授权状态码,但直接在浏览器地址栏访问API控制器地址却完全正常。数据库用的是ClearDB插件,MySQL Workbench连接也没毛病,这就让人很困惑了。

先贴一下我的AJAX调用代码:

getPlaylist : function() { 
  $.ajax({ 
    type : 'GET', 
    url : basePath + '/songs', 
    dataType : 'json', 
    contentType : 'application/json',
    success : function(songs) { 
      $('#radioPlaylist').empty(); 
      for (let song of songs) { 
        $('#radioPlaylist').append( 
          '<div class="form-group">' + 
          '<input type="text" class="form-control songText" value="#'+ song.id + ' '+ song.title + '" disabled="disabled">' + 
          '</div>'); 
      } 
    } 
  }); 
}

另外我也抓了请求头和响应头的信息:

响应头:Cache-Control: no-cache, no-store, max-age=0, must-revalidate; Connection: keep-alive; Content-Type:application/json;charset=UTF-8; Date:at, 09 Mar 2019 16:07:20 GMT; Expires:0; Pragma:no-cache; Server:Cowboy; Strict-Transport-Security:max-age=31536000 ; includeSubDomains; Transfer-Encoding:chunked; Via :1.1 vegur; X-Content-Type-Options :nosniff; X-Frame-Options:DENY; X-Xss-Protection:1; mode=block

请求头:Accept:application/json, text/javascript, /; q=0.01; Accept-Encoding :gzip, deflate, br; Accept-Language: en-GB,en;q=0.5; Connection: keep-alive; Host:portfolio-st.herokuapp.com; Referer:https://portfolio-st.herokuapp.com/; User-Agent:Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/65.0; X-Requested-With:XMLHttpRequest

可能的原因和解决步骤

1. 会话Cookie未被AJAX请求携带

直接在浏览器访问API时,浏览器会自动带上当前会话的Cookie,但AJAX请求有时候可能因为配置问题没带上——特别是如果后端依赖会话认证(比如Spring Security这类框架),没有Cookie的话后端就会认为你未授权。

你可以先打开浏览器开发者工具(F12),切换到Network标签,找到这个/songs的AJAX请求,查看Request Headers里有没有Cookie字段。如果没有,试试在AJAX配置里加上xhrFields: { withCredentials: true },强制带上凭证:

getPlaylist : function() { 
  $.ajax({ 
    type : 'GET', 
    url : basePath + '/songs', 
    dataType : 'json', 
    contentType : 'application/json',
    xhrFields: {
      withCredentials: true // 新增配置
    },
    success : function(songs) { 
      $('#radioPlaylist').empty(); 
      for (let song of songs) { 
        $('#radioPlaylist').append( 
          '<div class="form-group">' + 
          '<input type="text" class="form-control songText" value="#'+ song.id + ' '+ song.title + '" disabled="disabled">' + 
          '</div>'); 
      } 
    } 
  }); 
}

2. CSRF令牌验证失败

如果后端启用了CSRF防护(比如Spring Security默认开启),AJAX请求需要带上CSRF令牌,而直接访问浏览器的GET请求可能不会触发CSRF验证(部分框架只对POST/PUT/DELETE等修改请求验证,但有些会强制所有请求都验证)。

解决方法是在页面里添加CSRF令牌的meta标签(如果后端是Spring Boot,通常会自动生成,或者你手动添加):

<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>

然后在AJAX请求里带上这个令牌:

getPlaylist : function() { 
  var token = $("meta[name='_csrf']").attr("content");
  var header = $("meta[name='_csrf_header']").attr("content");
  
  $.ajax({ 
    type : 'GET', 
    url : basePath + '/songs', 
    dataType : 'json', 
    contentType : 'application/json',
    beforeSend: function(xhr) {
      xhr.setRequestHeader(header, token); // 新增令牌头
    },
    success : function(songs) { 
      $('#radioPlaylist').empty(); 
      for (let song of songs) { 
        $('#radioPlaylist').append( 
          '<div class="form-group">' + 
          '<input type="text" class="form-control songText" value="#'+ song.id + ' '+ song.title + '" disabled="disabled">' + 
          '</div>'); 
      } 
    } 
  }); 
}

3. 检查basePath是否正确

虽然直接访问API地址正常,但还是确认下basePath的值是不是https://portfolio-st.herokuapp.com/api,如果拼接后的URL有误,也可能导致奇怪的问题。

4. 查看Heroku后端日志

最直接的方法是看后端到底为什么返回401,执行heroku logs --tail命令查看Heroku的实时日志,里面会有详细的错误原因,比如是会话不存在、权限不足还是CSRF验证失败,能帮你快速定位问题。

内容的提问来源于stack exchange,提问作者Stefan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:19:15