Automatically retry AJAX request with new CSRF token if token error is returned

다른 탭에서 로그아웃했다가 다시 로그인한 후 exec_json을 시도하는 등,
사용자가 보기에는 정상적인 상황인데도 보안정책(CSRF) 오류가 발생할 수 있음.
이 때 자연스럽게 토큰을 갱신한 후 요청을 다시 전송하도록 개선함.
This commit is contained in:
Kijin Sung 2022-10-20 16:56:47 +09:00
parent ed649fb58c
commit de7bf0a0a6
2 changed files with 21 additions and 5 deletions

View file

@ -53,12 +53,19 @@
};
/**
* @brief Get CSRF token for the document
* Get CSRF token for the document
*/
window.getCSRFToken = function() {
return $("meta[name='csrf-token']").attr("content");
};
/**
* Set CSRF token for the document
*/
window.setCSRFToken = function(token) {
$("meta[name='csrf-token']").attr("content", token);
};
/* Intercept jQuery AJAX calls to add CSRF headers */
$.ajaxPrefilter(function(options) {
if (!isSameOrigin(location.href, options.url)) return;

View file

@ -191,15 +191,15 @@
window.exec_json = $.exec_json = function(action, params, callback_success, callback_error) {
// Convert params to object and fill in the module and act.
var action_parts = action.split('.');
var request_info;
if (action === 'raw') {
request_info = 'RAW FORM SUBMISSION';
} else {
params = params ? ($.isArray(params) ? arr2obj(params) : params) : {};
action = action.split(".");
//if (action.length != 2) return;
params.module = action[0];
params.act = action[1];
//if (action_parts.length != 2) return;
params.module = action_parts[0];
params.act = action_parts[1];
params._rx_ajax_compat = 'JSON';
params._rx_csrf_token = getCSRFToken();
request_info = params.module + "." + params.act;
@ -232,6 +232,15 @@
// If the response contains an error, display the error message.
if(data.error != "0" && data.error > -1000) {
// If this is a temporary CSRF error, retry with a new token.
if (data.errorDetail === 'ERR_CSRF_CHECK_FAILED' && action !== 'member.getLoginStatus') {
return window.exec_json('member.getLoginStatus', {}, function(data) {
if (data.csrf_token) {
setCSRFToken(data.csrf_token);
window.exec_json(action, params, callback_success, callback_error);
}
});
}
// Should not display the error message when the callback function returns false.
if ($.isFunction(callback_error) && callback_error(data) === false) {
return;