Created
April 8, 2022 02:39
-
-
Save relyky/3ed82b3296417ca10ffbe532a9c8e1e7 to your computer and use it in GitHub Desktop.
MVC5, AjaxWebApi, AjaxValidateAntiForgeryToken, AntiForgery, with axios
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Web; | |
using System.Web.Helpers; | |
using System.Web.Mvc; | |
using YourProject.DB; | |
using YourProject.Models; | |
namespace YourProject | |
{ | |
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | |
public class AjaxValidateAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter | |
{ | |
public void OnAuthorization(AuthorizationContext filterContext) | |
{ | |
try | |
{ | |
if (filterContext.HttpContext.Request.IsAjaxRequest()) | |
{ | |
ValidateRequestHeader(filterContext.HttpContext.Request); | |
} | |
else | |
{ | |
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.BadRequest); | |
} | |
} | |
catch (HttpAntiForgeryException ex) | |
{ | |
throw new HttpAntiForgeryException("The anti-forgery token not found", ex); | |
} | |
} | |
private void ValidateRequestHeader(HttpRequestBase request) | |
{ | |
string antiForgeryToken = request.Headers["RequestVerificationToken"]; | |
VerifyAntiForgeryToken(antiForgeryToken); | |
} | |
private void VerifyAntiForgeryToken(string antiForgeryToken) | |
{ | |
string cookieToken = String.Empty; | |
string formToken = String.Empty; | |
if (!String.IsNullOrEmpty(antiForgeryToken)) | |
{ | |
string[] tokens = antiForgeryToken.Split(':'); | |
if (tokens.Length == 2) | |
{ | |
cookieToken = tokens[0].Trim(); | |
formToken = tokens[1].Trim(); | |
} | |
} | |
AntiForgery.Validate(cookieToken, formToken); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Web; | |
using System.Web.Helpers; | |
using System.Web.Mvc; | |
using YourProject.DB; | |
using YourProject.Models; | |
namespace YourProject | |
{ | |
/// <summary> | |
/// HttpPost + AjaxValidateAntiForgeryToken + CatchAndLog | |
/// </summary> | |
public class AjaxWebApiAttribute : AjaxValidateAntiForgeryTokenAttribute, IExceptionFilter, IActionFilter | |
{ | |
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) | |
{ | |
} | |
/// <summary> | |
/// 實作[HttpPost] | |
/// </summary> | |
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) | |
{ | |
if (filterContext.HttpContext.Request.HttpMethod != "POST") | |
{ | |
filterContext.Result = new HttpNotFoundResult(); | |
} | |
} | |
/// <summary> | |
/// 實作[CatchAndLog] | |
/// </summary> | |
public void OnException(ExceptionContext filterContext) | |
{ | |
//System.Diagnostics.Debugger.Break(); | |
string errMsg = filterContext.Exception.Message; | |
// 記LOG | |
string traceMsg = $"[{filterContext.Exception.GetType().Name}] {errMsg} \r\nRawUrl:{filterContext.HttpContext.Request.RawUrl}"; | |
DBHelper.ExpLog("AjaxWebApi", "CatchAndLog", traceMsg, SysEnv.AuthUser?.UserId ?? ""); | |
// response 299 表示邏輯上的錯誤 | |
filterContext.ExceptionHandled = true; | |
filterContext.HttpContext.Response.StatusCode = 299; | |
filterContext.Result = new ContentResult | |
{ | |
Content = errMsg | |
}; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// ref→[axios - Config Defaults](https://github.com/axios/axios#config-defaults) | |
//axios.defaults.headers.common['Authorization'] = 'Bearer ' + AuthToken; | |
axios.defaults.headers.common['RequestVerificationToken'] = AntiForgeryToken; | |
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; // mark as an ajax request | |
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; | |
axios.defaults.validateStatus = (status) => (status >= 200 && status < 299); // 客製化讓 StatusCode 299 表示為邏輯上的錯誤訊息。 | |
///--------------------------------------------------------------- | |
/// CommonUtilities.js | |
/// 解析 Response 封包,並 alert 錯誤訊息 | |
export function castAlertPromise(originalPromise) { | |
return Promise.resolve(originalPromise).then(resp => { | |
//# success | |
console.info('castAlertPromise', { resp }); | |
return resp.data; | |
}).catch(xhr => { | |
//# fail | |
console.error('castAlertPromise FAIL1', { xhr }) | |
const errmsg = xhr.response.data | |
Swal.fire({ title: '執行失敗!', text: errmsg, icon: 'error' }); | |
throw errmsg; //※必需丟出錯誤訊息才會被browser視為執行失敗! | |
}); | |
} | |
///--------------------------------------------------------------- | |
/// apiClient.js | |
import axios from 'axios' | |
import { castAlertPromise } from './CommonUtilities.js' | |
const baseUrl = '/api/Controller/Action' | |
export default { | |
QryDataList: (args) => { | |
const url = `${baseUrl}/QryDataList` | |
return castAlertPromise(axios.post(url, args)) | |
}, | |
GetFormData: (args) => { | |
const url = `${baseUrl}/GetFormData` | |
return castAlertPromise(axios.post(url, args)) | |
}, | |
NewFormData: (args) => { | |
const url = `${baseUrl}/NewFormData` | |
return castAlertPromise(axios.post(url, args)) | |
}, | |
UpdFormData: (args) => { | |
const url = `${baseUrl}/UpdFormData` | |
return castAlertPromise(axios.post(url, args)) | |
}, | |
DelFormData: (args) => { | |
const url = `${baseUrl}/DelFormData` | |
return castAlertPromise(axios.post(url, args)) | |
}, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@functions { | |
public static string GetAntiForgeryToken() | |
{ | |
string cookieToken, formToken; | |
AntiForgery.GetTokens(null, out cookieToken, out formToken); | |
return string.Concat(cookieToken, ":", formToken); | |
} | |
public static string CalcFileHashCode(string filepath) | |
{ | |
using (var stream = File.OpenRead(Server.MapPath(filepath))) | |
using (var bufferedStream = new BufferedStream(stream, 1024 * 32)) | |
{ | |
var sha = new System.Security.Cryptography.SHA256Managed(); | |
byte[] checksum = sha.ComputeHash(bufferedStream); | |
return BitConverter.ToString(checksum).Replace("-", String.Empty); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment