[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f2Gd22YHZrXOCTMSxzN42n1jHQnNfMhaR39gxCWZpeyQ":3,"$fAGYmCrMBbG1ifn-FXHzNmqWk4GZIQW22Pg4pTBXu2CM":996},{"id":4,"title":5,"body":6,"date":983,"description":984,"extension":985,"icon":986,"meta":987,"navigation":130,"ogImage":988,"path":989,"published":130,"publishedAt":990,"seo":991,"stem":992,"tags":993,"updatedAt":990,"__hash__":995},"tech/tech/nuxt-basic-auth.md","Nuxt で Basic 認証を実装してみる",{"type":7,"value":8,"toc":971},"minimark",[9,13,17,20,32,36,42,45,50,756,760,877,884,887,890,899,909,912,916,926,929,950,953,956,967],[10,11,12],"h2",{"id":12},"はじめに",[14,15,16],"p",{},"Nuxt での Basic 認証を実装する方法について気になったので実装してみたときの備忘録です。",[10,18,19],{"id":19},"参考",[14,21,22,23,27,28,31],{},"サードパーティ製のモジュールとして公開されている ",[24,25,26],"code",{},"@kgierke/nuxt-basic-auth"," を参考に実装しました。",[29,30],"br",{},"\nこだわりがなければ、こちらをインストールして使用することをお勧めします。",[33,34],"external-link-card-wrapper",{"url":35},"https://github.com/kgierke/nuxt-basic-auth/tree/main",[14,37,38,39,41],{},"公式モジュールではないことと、最終更新日が8ヶ月前だったので自分で実装してみることにしました。",[29,40],{},"\n（全体に一律で認証をかけたいだけで、わざわざモジュール入れるほどではなかったので）",[10,43,44],{"id":44},"ソースコード",[46,47,49],"h3",{"id":48},"servermiddleware","server/middleware",[51,52,58],"pre",{"className":53,"code":54,"filename":55,"language":56,"meta":57,"style":57},"language-ts shiki shiki-themes material-theme-lighter github-dark-high-contrast github-dark","export default defineEventHandler((event) => {\n  const { basicAuth } = useRuntimeConfig()\n\n  // ローカルでは無視する\n  if (import.meta.dev) {\n    return\n  }\n\n  // allowedRoutes に指定されていればスキップする\n  if (basicAuth.allowedRoutes?.some((route: string) => {\n    const regex = new RegExp(route)\n\n    return regex.test(event.node.req.url || '')\n  })) {\n    return\n  }\n\n  // 認証を判定する真偽値\n  let authenticated = false\n\n  // Authorizationヘッダーから認証情報を取得する\n  const credentials = event.node.req.headers.authorization?.split(' ')[1]\n\n  if (credentials) {\n    // base64 形式から utf-8 の String へ変換する\n    const [username, password] = Buffer.from(credentials, 'base64').toString('utf-8').split(':')\n\n    // username と password が一致しているかどうか\n    authenticated = username === basicAuth.username && password === basicAuth.password\n\n    // 一致していれば認証通過\n    if (authenticated) return\n  }\n\n  // 一致していなければ Unauthorized レスポンスを返す\n  event.node.res.statusCode = 401\n  event.node.res.setHeader(\n    'WWW-Authenticate',\n    'Basic realm=\"Secure Area\", charset=\"UTF-8\"',\n  )\n  event.node.res.setHeader('Content-Type', 'text/plain; charset=utf-8')\n  event.node.res.end('Access denied')\n})\n\n","~/server/middleware/basic-auth.ts","ts","",[24,59,60,98,125,132,139,169,175,181,186,192,233,257,262,303,314,319,324,329,335,350,355,361,415,420,434,440,516,521,527,561,566,572,588,593,598,604,629,650,664,676,682,719,748],{"__ignoreMap":57},[61,62,65,69,72,76,80,83,87,90,94],"span",{"class":63,"line":64},"line",1,[61,66,68],{"class":67},"stP2V","export",[61,70,71],{"class":67}," default",[61,73,75],{"class":74},"s7KVs"," defineEventHandler",[61,77,79],{"class":78},"sipQf","(",[61,81,79],{"class":82},"sfFde",[61,84,86],{"class":85},"senS2","event",[61,88,89],{"class":82},")",[61,91,93],{"class":92},"sGRfs"," =>",[61,95,97],{"class":96},"seLpV"," {\n",[61,99,101,104,107,111,114,118,121],{"class":63,"line":100},2,[61,102,103],{"class":92},"  const",[61,105,106],{"class":96}," {",[61,108,110],{"class":109},"sSuNx"," basicAuth",[61,112,113],{"class":96}," }",[61,115,117],{"class":116},"sUBcA"," =",[61,119,120],{"class":74}," useRuntimeConfig",[61,122,124],{"class":123},"sLCpo","()\n",[61,126,128],{"class":63,"line":127},3,[61,129,131],{"emptyLinePlaceholder":130},true,"\n",[61,133,135],{"class":63,"line":134},4,[61,136,138],{"class":137},"sZPSj","  // ローカルでは無視する\n",[61,140,142,145,148,151,154,157,159,163,166],{"class":63,"line":141},5,[61,143,144],{"class":67},"  if",[61,146,147],{"class":123}," (",[61,149,150],{"class":67},"import",[61,152,153],{"class":96},".",[61,155,156],{"class":109},"meta",[61,158,153],{"class":96},[61,160,162],{"class":161},"sdyPO","dev",[61,164,165],{"class":123},") ",[61,167,168],{"class":96},"{\n",[61,170,172],{"class":63,"line":171},6,[61,173,174],{"class":67},"    return\n",[61,176,178],{"class":63,"line":177},7,[61,179,180],{"class":96},"  }\n",[61,182,184],{"class":63,"line":183},8,[61,185,131],{"emptyLinePlaceholder":130},[61,187,189],{"class":63,"line":188},9,[61,190,191],{"class":137},"  // allowedRoutes に指定されていればスキップする\n",[61,193,195,197,199,202,204,207,210,213,215,217,220,223,227,229,231],{"class":63,"line":194},10,[61,196,144],{"class":67},[61,198,147],{"class":123},[61,200,201],{"class":161},"basicAuth",[61,203,153],{"class":96},[61,205,206],{"class":161},"allowedRoutes",[61,208,209],{"class":96},"?.",[61,211,212],{"class":74},"some",[61,214,79],{"class":123},[61,216,79],{"class":96},[61,218,219],{"class":85},"route",[61,221,222],{"class":116},":",[61,224,226],{"class":225},"snYqn"," string",[61,228,89],{"class":96},[61,230,93],{"class":92},[61,232,97],{"class":96},[61,234,236,239,242,244,247,250,252,254],{"class":63,"line":235},11,[61,237,238],{"class":92},"    const",[61,240,241],{"class":109}," regex",[61,243,117],{"class":116},[61,245,246],{"class":116}," new",[61,248,249],{"class":74}," RegExp",[61,251,79],{"class":123},[61,253,219],{"class":161},[61,255,256],{"class":123},")\n",[61,258,260],{"class":63,"line":259},12,[61,261,131],{"emptyLinePlaceholder":130},[61,263,265,268,270,272,275,277,279,281,284,286,289,291,294,297,301],{"class":63,"line":264},13,[61,266,267],{"class":67},"    return",[61,269,241],{"class":161},[61,271,153],{"class":96},[61,273,274],{"class":74},"test",[61,276,79],{"class":123},[61,278,86],{"class":161},[61,280,153],{"class":96},[61,282,283],{"class":161},"node",[61,285,153],{"class":96},[61,287,288],{"class":161},"req",[61,290,153],{"class":96},[61,292,293],{"class":161},"url",[61,295,296],{"class":116}," ||",[61,298,300],{"class":299},"sPUPB"," ''",[61,302,256],{"class":123},[61,304,306,309,312],{"class":63,"line":305},14,[61,307,308],{"class":96},"  }",[61,310,311],{"class":123},")) ",[61,313,168],{"class":96},[61,315,317],{"class":63,"line":316},15,[61,318,174],{"class":67},[61,320,322],{"class":63,"line":321},16,[61,323,180],{"class":96},[61,325,327],{"class":63,"line":326},17,[61,328,131],{"emptyLinePlaceholder":130},[61,330,332],{"class":63,"line":331},18,[61,333,334],{"class":137},"  // 認証を判定する真偽値\n",[61,336,338,341,344,346],{"class":63,"line":337},19,[61,339,340],{"class":92},"  let",[61,342,343],{"class":161}," authenticated",[61,345,117],{"class":116},[61,347,349],{"class":348},"sBxIE"," false\n",[61,351,353],{"class":63,"line":352},20,[61,354,131],{"emptyLinePlaceholder":130},[61,356,358],{"class":63,"line":357},21,[61,359,360],{"class":137},"  // Authorizationヘッダーから認証情報を取得する\n",[61,362,364,366,369,371,374,376,378,380,382,384,387,389,392,394,397,399,402,405,408,412],{"class":63,"line":363},22,[61,365,103],{"class":92},[61,367,368],{"class":109}," credentials",[61,370,117],{"class":116},[61,372,373],{"class":161}," event",[61,375,153],{"class":96},[61,377,283],{"class":161},[61,379,153],{"class":96},[61,381,288],{"class":161},[61,383,153],{"class":96},[61,385,386],{"class":161},"headers",[61,388,153],{"class":96},[61,390,391],{"class":161},"authorization",[61,393,209],{"class":96},[61,395,396],{"class":74},"split",[61,398,79],{"class":123},[61,400,401],{"class":299},"'",[61,403,404],{"class":299}," '",[61,406,407],{"class":123},")[",[61,409,411],{"class":410},"sFHE5","1",[61,413,414],{"class":123},"]\n",[61,416,418],{"class":63,"line":417},23,[61,419,131],{"emptyLinePlaceholder":130},[61,421,423,425,427,430,432],{"class":63,"line":422},24,[61,424,144],{"class":67},[61,426,147],{"class":123},[61,428,429],{"class":161},"credentials",[61,431,165],{"class":123},[61,433,168],{"class":96},[61,435,437],{"class":63,"line":436},25,[61,438,439],{"class":137},"    // base64 形式から utf-8 の String へ変換する\n",[61,441,443,445,448,451,454,457,460,462,465,467,470,472,474,476,478,482,484,486,488,491,493,495,498,500,502,504,506,508,510,512,514],{"class":63,"line":442},26,[61,444,238],{"class":92},[61,446,447],{"class":96}," [",[61,449,450],{"class":109},"username",[61,452,453],{"class":96},",",[61,455,456],{"class":109}," password",[61,458,459],{"class":96},"]",[61,461,117],{"class":116},[61,463,464],{"class":161}," Buffer",[61,466,153],{"class":96},[61,468,469],{"class":74},"from",[61,471,79],{"class":123},[61,473,429],{"class":161},[61,475,453],{"class":96},[61,477,404],{"class":299},[61,479,481],{"class":480},"sSIes","base64",[61,483,401],{"class":299},[61,485,89],{"class":123},[61,487,153],{"class":96},[61,489,490],{"class":74},"toString",[61,492,79],{"class":123},[61,494,401],{"class":299},[61,496,497],{"class":480},"utf-8",[61,499,401],{"class":299},[61,501,89],{"class":123},[61,503,153],{"class":96},[61,505,396],{"class":74},[61,507,79],{"class":123},[61,509,401],{"class":299},[61,511,222],{"class":480},[61,513,401],{"class":299},[61,515,256],{"class":123},[61,517,519],{"class":63,"line":518},27,[61,520,131],{"emptyLinePlaceholder":130},[61,522,524],{"class":63,"line":523},28,[61,525,526],{"class":137},"    // username と password が一致しているかどうか\n",[61,528,530,533,535,538,541,543,545,547,550,552,554,556,558],{"class":63,"line":529},29,[61,531,532],{"class":161},"    authenticated",[61,534,117],{"class":116},[61,536,537],{"class":161}," username",[61,539,540],{"class":116}," ===",[61,542,110],{"class":161},[61,544,153],{"class":96},[61,546,450],{"class":161},[61,548,549],{"class":116}," &&",[61,551,456],{"class":161},[61,553,540],{"class":116},[61,555,110],{"class":161},[61,557,153],{"class":96},[61,559,560],{"class":161},"password\n",[61,562,564],{"class":63,"line":563},30,[61,565,131],{"emptyLinePlaceholder":130},[61,567,569],{"class":63,"line":568},31,[61,570,571],{"class":137},"    // 一致していれば認証通過\n",[61,573,575,578,580,583,585],{"class":63,"line":574},32,[61,576,577],{"class":67},"    if",[61,579,147],{"class":123},[61,581,582],{"class":161},"authenticated",[61,584,165],{"class":123},[61,586,587],{"class":67},"return\n",[61,589,591],{"class":63,"line":590},33,[61,592,180],{"class":96},[61,594,596],{"class":63,"line":595},34,[61,597,131],{"emptyLinePlaceholder":130},[61,599,601],{"class":63,"line":600},35,[61,602,603],{"class":137},"  // 一致していなければ Unauthorized レスポンスを返す\n",[61,605,607,610,612,614,616,619,621,624,626],{"class":63,"line":606},36,[61,608,609],{"class":161},"  event",[61,611,153],{"class":96},[61,613,283],{"class":161},[61,615,153],{"class":96},[61,617,618],{"class":161},"res",[61,620,153],{"class":96},[61,622,623],{"class":161},"statusCode",[61,625,117],{"class":116},[61,627,628],{"class":410}," 401\n",[61,630,632,634,636,638,640,642,644,647],{"class":63,"line":631},37,[61,633,609],{"class":161},[61,635,153],{"class":96},[61,637,283],{"class":161},[61,639,153],{"class":96},[61,641,618],{"class":161},[61,643,153],{"class":96},[61,645,646],{"class":74},"setHeader",[61,648,649],{"class":123},"(\n",[61,651,653,656,659,661],{"class":63,"line":652},38,[61,654,655],{"class":299},"    '",[61,657,658],{"class":480},"WWW-Authenticate",[61,660,401],{"class":299},[61,662,663],{"class":96},",\n",[61,665,667,669,672,674],{"class":63,"line":666},39,[61,668,655],{"class":299},[61,670,671],{"class":480},"Basic realm=\"Secure Area\", charset=\"UTF-8\"",[61,673,401],{"class":299},[61,675,663],{"class":96},[61,677,679],{"class":63,"line":678},40,[61,680,681],{"class":123},"  )\n",[61,683,685,687,689,691,693,695,697,699,701,703,706,708,710,712,715,717],{"class":63,"line":684},41,[61,686,609],{"class":161},[61,688,153],{"class":96},[61,690,283],{"class":161},[61,692,153],{"class":96},[61,694,618],{"class":161},[61,696,153],{"class":96},[61,698,646],{"class":74},[61,700,79],{"class":123},[61,702,401],{"class":299},[61,704,705],{"class":480},"Content-Type",[61,707,401],{"class":299},[61,709,453],{"class":96},[61,711,404],{"class":299},[61,713,714],{"class":480},"text/plain; charset=utf-8",[61,716,401],{"class":299},[61,718,256],{"class":123},[61,720,722,724,726,728,730,732,734,737,739,741,744,746],{"class":63,"line":721},42,[61,723,609],{"class":161},[61,725,153],{"class":96},[61,727,283],{"class":161},[61,729,153],{"class":96},[61,731,618],{"class":161},[61,733,153],{"class":96},[61,735,736],{"class":74},"end",[61,738,79],{"class":123},[61,740,401],{"class":299},[61,742,743],{"class":480},"Access denied",[61,745,401],{"class":299},[61,747,256],{"class":123},[61,749,751,754],{"class":63,"line":750},43,[61,752,753],{"class":96},"}",[61,755,256],{"class":78},[46,757,759],{"id":758},"nuxtconfig","nuxt.config",[51,761,764],{"className":53,"code":762,"filename":763,"language":56,"meta":57,"style":57},"// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n    // ...\n  runtimeConfig: {\n    basicAuth: {\n        // 認証情報を管理する\n      username: 'admin',\n      password: 'admin',\n      allowedRoutes: [],\n    },\n  },\n  // ...\n})\n\n","~/nuxt.config.ts",[24,765,766,771,784,789,798,807,812,828,843,855,860,866,871],{"__ignoreMap":57},[61,767,768],{"class":63,"line":64},[61,769,770],{"class":137},"// https://nuxt.com/docs/api/configuration/nuxt-config\n",[61,772,773,775,777,780,782],{"class":63,"line":100},[61,774,68],{"class":67},[61,776,71],{"class":67},[61,778,779],{"class":74}," defineNuxtConfig",[61,781,79],{"class":78},[61,783,168],{"class":82},[61,785,786],{"class":63,"line":127},[61,787,788],{"class":137},"    // ...\n",[61,790,791,794,796],{"class":63,"line":134},[61,792,793],{"class":123},"  runtimeConfig",[61,795,222],{"class":96},[61,797,97],{"class":96},[61,799,800,803,805],{"class":63,"line":141},[61,801,802],{"class":123},"    basicAuth",[61,804,222],{"class":96},[61,806,97],{"class":96},[61,808,809],{"class":63,"line":171},[61,810,811],{"class":137},"        // 認証情報を管理する\n",[61,813,814,817,819,821,824,826],{"class":63,"line":177},[61,815,816],{"class":123},"      username",[61,818,222],{"class":96},[61,820,404],{"class":299},[61,822,823],{"class":480},"admin",[61,825,401],{"class":299},[61,827,663],{"class":96},[61,829,830,833,835,837,839,841],{"class":63,"line":183},[61,831,832],{"class":123},"      password",[61,834,222],{"class":96},[61,836,404],{"class":299},[61,838,823],{"class":480},[61,840,401],{"class":299},[61,842,663],{"class":96},[61,844,845,848,850,853],{"class":63,"line":188},[61,846,847],{"class":123},"      allowedRoutes",[61,849,222],{"class":96},[61,851,852],{"class":161}," []",[61,854,663],{"class":96},[61,856,857],{"class":63,"line":194},[61,858,859],{"class":96},"    },\n",[61,861,862,864],{"class":63,"line":235},[61,863,308],{"class":96},[61,865,663],{"class":82},[61,867,868],{"class":63,"line":259},[61,869,870],{"class":137},"  // ...\n",[61,872,873,875],{"class":63,"line":264},[61,874,753],{"class":82},[61,876,256],{"class":78},[14,878,879,880,883],{},"GitHubに公開したくなければ ",[24,881,882],{},".env"," などで管理しましょう。",[10,885,886],{"id":886},"使ってみる",[14,888,889],{},"実際に Basic 認証をかけたページを用意してみました。",[14,891,892],{},[893,894,898],"a",{"href":895,"rel":896},"https://tsukiyama.blog/basic-auth",[897],"nofollow","Basic認証サンプルページ",[14,900,901,904,906],{},[24,902,903],{},"username: admin",[29,905],{},[24,907,908],{},"password: admin",[14,910,911],{},"で通過できます。",[46,913,915],{"id":914},"️-注意","⚠️ 注意",[14,917,918,920,921,925],{},[24,919,49],{}," に実装しているので、SSR時の画面ロードではBasic 認証がかかりますが、",[922,923,924],"strong",{},"CSR時にはかかりません","。",[14,927,928],{},"ページ全体に認証をかける場合は問題ないのですが、特定のページだけ認証をかけたい場合は以下の対応も必要になります。",[930,931,932,939],"ul",{},[933,934,935,938],"li",{},[24,936,937],{},"middleware/"," にもチェックを追加する",[933,940,941,942,945,946,949],{},"Basic認証を適用するページへは、クライアントサイドルーティングを避けるために ",[24,943,944],{},"\u003CNuxtLink>"," に ",[24,947,948],{},"external"," を付けて遷移させる",[14,951,952],{},"ただ、特定のページだけ認証を付与するユースケースは一般的ではないと思うので具体的な対応方針については本記事では割愛しています。",[10,954,955],{"id":955},"まとめ",[930,957,958,964],{},[933,959,960,961,963],{},"Nuxt での Basic認証 は ",[24,962,49],{}," で実装する",[933,965,966],{},"CSR時にはBasic認証がかからないので別途対応が必要である",[968,969,970],"style",{},"html pre.shiki code .stP2V, html code.shiki .stP2V{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#FF9492;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .s7KVs, html code.shiki .s7KVs{--shiki-light:#6182B8;--shiki-default:#DBB7FF;--shiki-dark:#B392F0}html pre.shiki code .sipQf, html code.shiki .sipQf{--shiki-light:#90A4AE;--shiki-default:#FFB757;--shiki-dark:#E1E4E8}html pre.shiki code .sfFde, html code.shiki .sfFde{--shiki-light:#39ADB5;--shiki-default:#FFB757;--shiki-dark:#E1E4E8}html pre.shiki code .senS2, html code.shiki .senS2{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#FFB757;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sGRfs, html code.shiki .sGRfs{--shiki-light:#9C3EDA;--shiki-default:#FF9492;--shiki-dark:#F97583}html pre.shiki code .seLpV, html code.shiki .seLpV{--shiki-light:#39ADB5;--shiki-default:#F0F3F6;--shiki-dark:#E1E4E8}html pre.shiki code .sSuNx, html code.shiki .sSuNx{--shiki-light:#90A4AE;--shiki-default:#91CBFF;--shiki-dark:#79B8FF}html pre.shiki code .sUBcA, html code.shiki .sUBcA{--shiki-light:#39ADB5;--shiki-default:#FF9492;--shiki-dark:#F97583}html pre.shiki code .sLCpo, html code.shiki .sLCpo{--shiki-light:#E53935;--shiki-default:#F0F3F6;--shiki-dark:#E1E4E8}html pre.shiki code .sZPSj, html code.shiki .sZPSj{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#BDC4CC;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sdyPO, html code.shiki .sdyPO{--shiki-light:#90A4AE;--shiki-default:#F0F3F6;--shiki-dark:#E1E4E8}html pre.shiki code .snYqn, html code.shiki .snYqn{--shiki-light:#E2931D;--shiki-default:#91CBFF;--shiki-dark:#79B8FF}html pre.shiki code .sPUPB, html code.shiki .sPUPB{--shiki-light:#39ADB5;--shiki-default:#ADDCFF;--shiki-dark:#9ECBFF}html pre.shiki code .sBxIE, html code.shiki .sBxIE{--shiki-light:#FF5370;--shiki-default:#91CBFF;--shiki-dark:#79B8FF}html pre.shiki code .sFHE5, html code.shiki .sFHE5{--shiki-light:#F76D47;--shiki-default:#91CBFF;--shiki-dark:#79B8FF}html pre.shiki code .sSIes, html code.shiki .sSIes{--shiki-light:#91B859;--shiki-default:#ADDCFF;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":57,"searchDepth":127,"depth":127,"links":972},[973,974,975,979,982],{"id":12,"depth":100,"text":12},{"id":19,"depth":100,"text":19},{"id":44,"depth":100,"text":44,"children":976},[977,978],{"id":48,"depth":127,"text":49},{"id":758,"depth":127,"text":759},{"id":886,"depth":100,"text":886,"children":980},[981],{"id":914,"depth":127,"text":915},{"id":955,"depth":100,"text":955},"2025-06-06T00:00:00.000Z","Nuxt で Basic 認証を実装する備忘録です。","md","/avatar_green_oab8qx.webp",{},"https://res.cloudinary.com/dyoyv8djx/image/upload/v1749222843/tsukiyama-blog/nuxt-basic-auth/nuxt-basic-auth_kj3jlm.png","/tech/nuxt-basic-auth",null,{"title":5,"description":984},"tech/nuxt-basic-auth",[994],"Nuxt.js","N9N6ezA27w3UwTuv-12SLhiXp8Ou-nDsEOuE7Gmf0LA",{"title":997,"image":998,"description":999},"GitHub - kgierke/nuxt-basic-auth: Nuxt 3 Module for Basic Authentication","https://opengraph.githubassets.com/5d1f729d48a26025fa170026900209460358afd84bb90e67b77dc52a3bbdebfc/kgierke/nuxt-basic-auth","Nuxt 3 Module for Basic Authentication. Contribute to kgierke/nuxt-basic-auth development by creating an account on GitHub."]