1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| import { getCookies, setCookie, computeHmacTokenPair, computeVerifyHmacTokenPair, Session, Context, MemoryStore, SqliteStore, RedisStore, WebdisStore, Cookie, Middleware, } from "./deps.ts";
type Store = MemoryStore | SqliteStore | RedisStore | WebdisStore | null;
interface VerifyState { state: boolean; redirectPath: string; message: string; }
const getTask = async function (ctx: Context, key: string): Promise<void> { const tokenPair = computeHmacTokenPair(key, 360);
await ctx.state.session.set("csrfToken", tokenPair.tokenStr);
const cookie: Cookie = { name: "cookies_token", value: tokenPair.cookieStr, }; setCookie(ctx.response, cookie); };
const postTask = async function ( ctx: Context, key: string ): Promise<VerifyState> { const value = await ctx.request.body({ type: "form" }).value; const csrfToken = value.get("csrf_token"); const cookies = getCookies(ctx.request);
const referer = ctx.request.headers.get("referer");
let state = false, redirectPath = "", message = "";
if (!referer) { message = "Not huve referer!"; redirectPath = "/"; return { state, redirectPath, message }; }
if (!csrfToken) { message = "Not found csrf token into form!"; ctx.state.session.flash("csrfUnVerify", true); redirectPath = referer; return { state, redirectPath, message }; }
if (!computeVerifyHmacTokenPair(key, csrfToken, cookies.cookies_token)) { message = "Not verify csrf token!"; ctx.state.session.flash("csrfUnVerify", true); redirectPath = referer; return { state, redirectPath, message }; }
state = true; return { state, redirectPath, message }; };
export class CsrfVerify extends Session { private key: string;
constructor(key: string, store: Store = null) { super(store || null); this.key = key; } verify(): Middleware { const verifyFunc = async ( ctx: Context, next: () => Promise<void> ): Promise<void> => { const sid = await ctx.cookies.get("sid");
if (sid && (await this.sessionExists(sid))) { ctx.state.session = this.getSession(sid); } else { ctx.state.session = await this.createSession(); ctx.cookies.set("sid", ctx.state.session.id); }
if (ctx.request.method === "GET") { await getTask(ctx, this.key); } else if (ctx.request.method === "POST") { const { state, redirectPath, message } = await postTask(ctx, this.key);
if (!state) { console.error(message); return ctx.response.redirect(redirectPath); }
await getTask(ctx, this.key); } ctx.state.session.set("_flash", {});
await next(); }; return verifyFunc as Middleware; } }
|