我尝试使用jquery ajax post方法提交数据,但到目前为止我没有这样做。我使用的是spring security 4.0.4.RELEASE和Spring framework 4.2.5.RELEASE。经过这么多吨谷歌搜索为什么GET工作和POST没有。我发现_csrf令牌有一些事情要做,为什么不允许使用POST方法。我尝试在URL处添加令牌,然后它现在允许POST方法,但它为传递给data参数的所有数据检索空值。这是我的示例代码。
控制器:
@RequestMapping(value = "/ajaxAddDeliveryType", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public JsonResponse addDeliveryType(
@ModelAttribute(value = "delivery") DeliveryType deliveryType,
BindingResult result) {
System.out.println("deliveryType "+deliveryType.toString());
JsonResponse res = new JsonResponse();
/* Validate all the input. it return "SUCCESS" or "FAIL" status */
jsonResponse(res, result, deliveryType);
if (res.getStatus().equalsIgnoreCase("success")) {
/*
* If result status is Success insert the data into database
*/
deliveryTypeService.saveDeliveryType(deliveryType);
}
return res;
}
/*
* This method will validate all input field in form and returning response.
* If result has error detected it will set the status to "FAIL". If no
* error occured in result it will set the status to "SUCCESS".
*/
public JsonResponse jsonResponse(JsonResponse res, BindingResult result,
DeliveryType deliveryType) {
/* Set error message if text field is empty */
ValidationUtils.rejectIfEmptyOrWhitespace(result,
"mainte_delivery_type", "Delivery type can not be empty");
ValidationUtils.rejectIfEmptyOrWhitespace(result, "delivery_weight",
"Delivery weight not be empty");
ValidationUtils.rejectIfEmptyOrWhitespace(result, "delivery_price",
"Delivery price can not be empty.");
if (!deliveryTypeService.isDeliveryTypeUnique(deliveryType.getId(),
deliveryType.getMainte_delivery_type())) {
/* Set status to fail */
res.setStatus("FAIL");
/* Set error message if delivery type already exist */
result.rejectValue("mainte_delivery_type",
"Delivery type already exists. Please fill in different value");
res.setResult(result.getAllErrors());
}
if (result.hasErrors()) {
/* Set status to fail */
res.setStatus("FAIL");
/*
* Collect all error messages for text field that not properly
* assign value
*/
res.setResult(result.getAllErrors());
}
/* Validate if the weight or price is more than zero / 0 */
else if (deliveryType.getDelivery_price().toString()
.equalsIgnoreCase("0")
|| deliveryType.getDelivery_weight().toString()
.equalsIgnoreCase("0")) {
/* Set status to fail */
res.setStatus("FAIL");
/* Set error message if delivery type already exist */
result.rejectValue("delivery_price",
"Delivery weight/price value should be more than '0'");
res.setResult(result.getAllErrors());
}
else {
deliveryTypes.clear(); /* Clear array list */
deliveryTypes.add(deliveryType);
/*
* Add employee model object into list
*/
res.setStatus("SUCCESS"); /* Set status to success */
res.setResult(deliveryTypes); /* Return object into list */
}
return res;
}
提交ajax POST方法时的控制台输出:
> deliveryType DeliveryType [id=0, mainte_delivery_type=null, delivery_price=null, delivery_weight=null]
提交ajax GET方法时的控制台输出:
deliveryType DeliveryType [id=0, mainte_delivery_type=test, delivery_price=123, delivery_weight=12]
Javacript代码:
/*
* This function will validate all the input field inside the form and return a
* response if result got an error. otherwise if no error in result is found it
* will insert the data into database
*/
function validateAndInsertUsingAjax(action, message) {
/* Disable button to prevent redundant ajax request */
$("#btnDeliveryType").prop('disabled', true);
var datastring = $("#myform").serialize();
$.ajax({
type : "GET",
url : myContext + '/' + action+ '?_csrf=' + $("#token").val(),
data : datastring,
contentType : "application/json; charset=utf-8",
datatype : "json",
crossDomain : "TRUE",
success : function(response) {
var stringResponse = JSON.stringify(response)
// we have the response
console.log("response " + stringResponse);
var obj = JSON.parse(stringResponse);
if (obj.status == "SUCCESS") {
/*
* Enable button to make ajax request again after response
* return
*/
$("#btnDeliveryType").prop('disabled', false);
var userInfo = "<ol>";
for (i = 0; i < obj.result.length; i++) {
/* Create html elements */
userInfo += "<br><li><b>Delivery Type</b> : "
+ obj.result[i].mainte_delivery_type;
userInfo += "<br><li><b>Delivery weight (kg)</b> : "
+ obj.result[i].delivery_weight;
userInfo += "<br><li><b>Delivery Price</b> : "
+ obj.result[i].delivery_price;
}
userInfo += "</ol>";
/* Draw message in #info div */
$('#info').html(message + userInfo);
/* Show and hide div */
$('#error').hide('slow');
$('#info').show('slow');
/* Populate DataTable */
populateDataTable();
/* Hide modal */
$('#modalAddDeliveryType').modal('hide');
} else {
/*
* Enable button to make ajax request again after response
* return
*/
$("#btnDeliveryType").prop('disabled', false);
var errorInfo = "";
for (i = 0; i < response.result.length; i++) {
errorInfo += "<br>" + (i + 1) + ". "
+ response.result[i].code;
}
/* Show error message from response */
$('#error').html(
"Please correct following errors: " + errorInfo);
/* Show and hide div */
$('#info').hide('slow');
$('#error').show('slow');
}
},
/* xhr.status shows server respond */
error : function(xhr, desc, err) {
/*
* Enable button to make ajax request again after response return
*/
$("#btnDeliveryType").prop('disabled', false);
if (xhr.status == 500) {
alert('Error: ' + "Server not respond ");
}
if (xhr.status == 403) {
alert('Error: ' + "Access Denied");
}
}
});
}
JSP页面:
<div class="modal fade" id="modalAddDeliveryType" tabindex="-1"
role="dialog" aria-labelledby="exampleModalCenterTitle"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="exampleModalLongTitle"></h3>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<input type="hidden" id="token" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<!-- Form Text field -->
<form:form method="GET" modelAttribute="delivery" name="myform"
id="myform">
<form:input type="hidden" path="id" id="id" />
<div class="modal-body">
<!-- Input Delivery type -->
<div>
<label for="mainte_delivery_type">Delivery type: </label>
<form:input path="mainte_delivery_type" id="mainte_delivery_type"
class="form-control" placeholder="Delivery type" />
<form:errors path="mainte_delivery_type" cssClass="error" />
</div>
<!-- Input Delivery weight -->
<div>
<label for="delivery_weight">Delivery weight (kg): </label>
<form:input type="number" min="0" path="delivery_weight"
id="delivery_weight" class="form-control"
placeholder="Delivery weight(kg)" />
<form:errors path="delivery_weight" cssClass="error" />
</div>
<!-- Input Delivery price -->
<div>
<label for="delivery_price">Delivery price: </label>
<form:input type="number" min="0" path="delivery_price"
id="delivery_price" class="form-control"
placeholder="Delivery price" />
<form:errors path="delivery_price" cssClass="error" />
</div>
<div id="error" class="error"></div>
</div>
<div class="modal-footer">
<!-- Close button -->
<button type="button" class="btn btn-secondary"
data-dismiss="modal">Close</button>
<!-- Register button -->
<input type="submit" class="btn btn-primary" value="Save"
id="btnDeliveryType" onClick="insertOrUpdateDeliveryType()" />
</div>
</form:form>
</div>
</div>
</div>
我希望有人能为我提供更好的方法来实现这个POST方法。我是春天安全的新人。
答案 0 :(得分:0)
CSRF令牌用于防止远程第三方伪造请求。基本上,攻击者将完全按原样复制表单,然后强制在攻击者控制的网站上的毫无戒心的用户,代表用户发送请求,该请求将不可避免地包括用户的cookie,通常是合法的网站。
因此,CSRF令牌至少可以随机说出,并锁定会话。它就像在您提交的每个表单中包含一个cookie,GET请求也应包括这些,只要一个操作正在完成。
假设您没有尝试在此处执行任何恶意操作并完全控制您的机器人,您可以轻松地向网站发送初始GET请求,建立会话,并从HTML中获取您的会话唯一的CSRF令牌(将作为ctrlKey
标记内的值嵌入。)
编辑:顺便说一句,如果您控制目标站点(生成此CSRF令牌的站点!),那么显然您可以将自己列入白名单,或通过AJAX将该信息专门发送给用户。如果是这种情况,有办法解决这个问题。