【问题标题】:Why does beforeSend in $ajaxSetup not add parameters to a parameter-less function?为什么 $ajaxSetup 中的 beforeSend 不向无参数函数添加参数?
【发布时间】:2021-01-10 16:32:26
【问题描述】:

我正在尝试将安全令牌添加到我的所有 AJAX $.post 调用中。

我将安全令牌设置为使用 following code 自动添加

$.ajaxSetup({
     beforeSend: function (jqXHR, settings) {
        settings.data += "&sessionID="+v_sessionID;
  }
});

然后像下面这样的代码,将自动附加安全令牌

$.post("ajax/p_getOnePosition.jsp", {
    positionNo: positionNo,
}, function(response2) {

代码运行良好,但不适用于没有参数的函数,例如

$.post("ajax/p_clearFilters.jsp", {

}, function(response2) {

知道为什么会这样吗?

我可以通过简单地在代码中添加一个虚拟参数dummy:1 来修复它

 $.post("ajax/p_clearFilters.jsp", {
       dummy:1
    }, function(response2) {

所以我试着去做

 $.ajaxSetup({
     beforeSend: function (jqXHR, settings) {
        var noParameters=(settings.data==null || settings.data==undefined || settings.data=='');
        settings.data += (noParameters?"dummy=1":"") +"&sessionID="+v_sessionID;
  }
});

但这并没有模仿手动添加dummy=1,并且请求中没有安全令牌。

更新

回想起来(在@Rory McCrossan 的评论和@Louys Patrice Bessette 的回答之后)我意识到我的问题是不完整的。我还应该在我的问题中包含用于检索参数的 JSP 代码。

<%
String csrfSessionID = SecurityIssues.StringToAlphaNumericStr(request.getParameter("sessionID"));
%>

【问题讨论】:

  • 我无法复制该问题:jsfiddle.net/RoryMcCrossan/5ng8kohm。如果您在控制台的网络选项卡中检查请求,您将在请求负载中看到 &amp;sessionId 值。 但是在这种情况下,密钥上的前导 &amp; 可能会导致您的服务器端出现问题。尝试改进逻辑,以便仅在必要时添加 &amp;。
  • 非常感谢@RoryMcCrossan 花时间尝试复制问题。通过运行您的代码,我看到 - 正如您所写 - sessionId 值在“请求有效负载”中。但是当 //positionNo:1 未注释时,PositionNo 和 sessionId 值都显示为“表单数据”。看来我只能从“表单数据”而不是“请求有效负载”中成功检索数据。任何想法为什么会这样?
  • 我也确实尝试在问题末尾的代码中处理领先的&amp;。谢谢!

标签: jquery ajax post


【解决方案1】:

您有三个data 案例:

  • 未定义
  • 空
  • 不为空

试试beforeSend函数:

$.ajaxSetup({
  beforeSend: function (jqXHR, settings) {
    
    // Undefined data
    settings.data = settings.data === undefined ? "" : settings.data;

    // Add the & or not in front of the sessionID
    settings.data +=
      (settings.data.length > 0 ? "&" : "") + "sessionID=SESSION_ID";
    console.log("before send:", settings.data);
    
  }
});

下面的 sn-p 总是以错误结束,因为请求的 url 是https://example.com。 ;)

$.ajaxSetup({
  beforeSend: function (jqXHR, settings) {
    
    // Undefined data
    settings.data = settings.data === undefined ? "" : settings.data;

    // Add the & or not in front of the sessionID
    settings.data +=
      (settings.data.length > 0 ? "&" : "") + "sessionID=SESSION_ID";
    console.log("before send:", settings.data);
    
  }
});

$(".test").on("submit", function (e) {
  console.clear();
  e.preventDefault();

  let formId = $(this)[0].id;
  console.log( `You are trying the ${formId}`);

  let formValues;
  switch (formId) {
    
    case "test_1":
      // Do not set formValues on purpose...
      break;
    
    case "test_2":
      formValues = {};
      break;

    case "test_3":
      formValues = { firstName: "John", lastName: "Doh" };
      break;

  }

  console.log("on submit:", formValues);

  $.post("https://example.com", formValues)
    .done(function () {
      console.log("DONE");
    })
    .fail(function () {
      console.error("ERROR - (obviously!) - Check the Network tab-> example.com -> Headers -> Form Data");
    });
});
button{
  margin: 1em;
  width: 20em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="test" id="test_1">
  <button>Test #1 - Send an undefined object</button>
</form>

<form class="test" id="test_2">
  <button>Test #2 - Send an empty object</button>
</form>

<form class="test" id="test_3">
  <button>Test #3 - Send an object</button>
</form>

同样在CodePen

【讨论】:

  • 非常感谢您的冗长、详细和有用的回答。在解决它之后,它让我找到了问题所在。我稍微更新了我的问题,因为我意识到回想起来它本来可以更完整。赞赏!
【解决方案2】:

在处理完@Rory McCrossan 的评论和@Louys Patrice Bessette 的回答后 - 非常感谢 - 我看到当 beforeSend 添加到空参数列表时,SESSIONID 作为请求有效负载的一部分发送,而当 beforeSend 添加到预先存在的参数列表,然后 SESSIONID 作为表单数据的一部分发送。这在检索参数时会有所不同。

对于作为表单数据一部分的数据,可以通过以下方式检索:

String csrfSessionID = SecurityIssues.StringToAlphaNumericStr(request.getParameter("sessionID"));

对于作为请求有效负载一部分的数据,可以通过以下方式检索: 请参阅@Fizer Khan 在Getting request payload from POST request in Java servlet 中的回答@

StringBuilder buffer = new StringBuilder();
java.io.BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
    buffer.append(line);
    buffer.append(System.lineSeparator());
}
String data = buffer.toString();
System.out.println("data:"+data);

这两个代码 sn-ps 互斥。第一个代码无法从请求负载中检索,第二个代码无法从表单数据中检索

请注意,在所有情况下,更好的答案可能会强制 beforeSend 在表单数据中发送 SessionID,但目前这是一个很好的解决方法!

【讨论】:

    猜你喜欢
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    • 2018-09-28
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多