ã¬ã¤ã
åºæ¬çãªä½¿ãæ¹
- ã¤ã³ã¹ãã¼ã«
- ã¯ããã«
- Vue ã¤ã³ã¹ã¿ã³ã¹
- ãã³ãã¬ã¼ãæ§æ
- ç®åºããããã£ã¨ã¦ã©ããã£
- ã¯ã©ã¹ã¨ã¹ã¿ã¤ã«ã®ãã¤ã³ãã£ã³ã°
- æ¡ä»¶ä»ãã¬ã³ããªã³ã°
- ãªã¹ãã¬ã³ããªã³ã°
- ã¤ãã³ããã³ããªã³ã°
- ãã©ã¼ã å ¥åãã¤ã³ãã£ã³ã°
- ã³ã³ãã¼ãã³ãã®åºæ¬
ã³ã³ãã¼ãã³ãã®è©³ç´°
- ã³ã³ãã¼ãã³ãã®ç»é²
- ããããã£
- ã«ã¹ã¿ã ã¤ãã³ã
- ã¹ããã
- åç & éåæã³ã³ãã¼ãã³ã
- ç¹å¥ãªåé¡ã«å¯¾å¦ãã
ãã©ã³ã¸ã·ã§ã³ã¨ã¢ãã¡ã¼ã·ã§ã³
- Enter/Leave ã¨ãã©ã³ã¸ã·ã§ã³ä¸è¦§
- ç¶æ ã®ãã©ã³ã¸ã·ã§ã³
åå©ç¨ã¨æ§æ
- ããã¯ã¹ã¤ã³
- ã«ã¹ã¿ã ãã£ã¬ã¯ãã£ã
- æç»é¢æ°ã¨JSX
- ãã©ã°ã¤ã³
- ãã£ã«ã¿ã¼
ãã¼ã«
- åä¸ãã¡ã¤ã«ã³ã³ãã¼ãã³ã
- ãã¹ã
- TypeScript ã®ãµãã¼ã
- ãããã¯ã·ã§ã³ç°å¢ã¸ã®é ä¿¡
ã¹ã±ã¼ã«ã¢ãã
- ã«ã¼ãã£ã³ã°
- ç¶æ 管ç
- ãµã¼ããµã¤ãã¬ã³ããªã³ã°
- ã»ãã¥ãªãã£
å é¨
- ãªã¢ã¯ãã£ãã®æ¢æ±
移è¡
- Vue 1.x ããã®ç§»è¡
- Vue Router 0.7.x ããã®ç§»è¡
- Vuex 0.6.x ãã 1.0 ã¸ã®ç§»è¡
ãã®ä»
- ä»ã®ãã¬ã¼ã ã¯ã¼ã¯ã¨ã®æ¯è¼
- Vue.js ã³ãã¥ããã£ã¸åå ãã¾ããã!
- ãã¼ã ã«ä¼ãã
v2.x 以åã®ããã¥ã¡ã³ãã§ãã v3.x ã®ããã¥ã¡ã³ããè¦ããå ´åã¯ãã¡ã
ã»ãã¥ãªãã£
æçµæ´æ°æ¥: 2020å¹´3æ20æ¥
èå¼±æ§ã®å ±å
èå¼±æ§ãå ±åãããå ´åãããã¯ç´ã¡ã«ç§éã«ã¨ã£ã¦æ大ã®èª²é¡ã¨ãªãããã«ã¿ã¤ã ã®ã³ã³ããªãã¥ã¼ã¿ããã®è§£æ±ºã«åãçµã¿ã¾ããèå¼±æ§ãå ±åããã«ã¯ [email protected] ã¸ã¡ã¼ã«ãéä¿¡ãã¦ãã ããã
æ°ããªèå¼±æ§ã®çºè¦ã¯ãã£ãã«ããã¾ãããã常㫠Vue ã¨ãã®å ¬å¼ã©ã¤ãã©ãªã®ææ°ãã¼ã¸ã§ã³ã使ç¨ããã¢ããªã±ã¼ã·ã§ã³ã®ã»ãã¥ãªãã£ãå¯è½ãªéãç¶æãããã¨ããå§ããã¾ãã
ã«ã¼ã« No.1: ä¿¡é ¼ã§ããªããã³ãã¬ã¼ãã絶対ã«ä½¿ããªã
Vue ã使ãã¨ãã®æãåºæ¬çãªã»ãã¥ãªãã£ã«ã¼ã«ã¯ãä¿¡é ¼ã§ããªãã³ã³ãã³ããã³ã³ãã¼ãã³ãã®ãã³ãã¬ã¼ãã¨ãã¦çµ¶å¯¾ã«ä½¿ããªã ã¨ãããã¨ã§ãããããããã¨ã¯ãããªãã®ã¢ããªã±ã¼ã·ã§ã³å ã§ä»»æã® JavaScript å®è¡ã許ãã¦ãã¾ããã¨ã¨åãã§ããããã«æªããã¨ã«ãã³ã¼ãããµã¼ãã¼ãµã¤ãã¬ã³ããªã³ã°ä¸ã«å®è¡ãããå ´åã«ã¯ããµã¼ãã¼å´ã®æ¬ é¥ã«ã¤ãªããã¾ããä¾ãã°ã次ã®ãããªä½¿ãæ¹ã§ã:
new Vue({
el: '#app',
template: `<div>` + userProvidedString + `</div>` // 絶対ã«ãã¦ã¯ãããªã
})
Vue ã®ãã³ãã¬ã¼ã㯠JavaScript ã«ã³ã³ãã¤ã«ããããã³ãã¬ã¼ãä¸ã®å¼ã¯ã¬ã³ããªã³ã°å¦çã®éç¨ã§å®è¡ããã¾ããå¼ã¯ç¹å®ã®ã¬ã³ããªã³ã°ã³ã³ããã¹ãã§è©ä¾¡ããã¾ãããæ½å¨çã«ã¯ã°ãã¼ãã«ã«å®è¡ãããè¤éãªå®è¡ç°å¢ã¨ãªããããVue ã®ãããªãã¬ã¼ã ã¯ã¼ã¯ã§ããã©ã¼ãã³ã¹ã®éç¾å®çãªãªã¼ãã¼ããããåãããã¨ãªãæªæã®ããã³ã¼ãå®è¡ãå®å ¨ã«é²ããã¨ã¯å°é£ã§ãããã®æã®åé¡ãåé¿ããæãç´æ¥çãªæ¹æ³ã¯ãå®å ¨ã«ããªãã®ç®¡çä¸ã«ããä¿¡é ¼ãããã³ã³ãã³ãã ãã Vue ãã³ãã¬ã¼ãã®ã³ã³ãã³ãã«ãããã¨ã§ãã
Vue ãè¡ã£ã¦ããã»ãã¥ãªãã£å¯¾ç
HTML ã³ã³ãã³ã
ãã³ãã¬ã¼ãã使ç¨ããå ´åããæç»é¢æ°ã使ç¨ããå ´åããã³ã³ãã³ãã¯èªåçã«ã¨ã¹ã±ã¼ãå¦çããã¾ããä¾ãã°ãã®ãããªãã³ãã¬ã¼ãã®å ´å:
<h1>{{ userProvidedString }}</h1>
ãã userProvidedString
ã«ä»¥ä¸ãå«ã¾ãã¦ããã¨:
'<script>alert("hi")</script>'
以ä¸ã®ããã«ã¨ã¹ã±ã¼ãããã HTML ã«ãªãã¾ãã
<script>alert("hi")</script>
Vue ã§ã¯ããã®ããã«ã¹ã¯ãªããã®ã¤ã³ã¸ã§ã¯ã·ã§ã³ãé²ãã¾ãããã®ã¨ã¹ã±ã¼ãå¦ç㯠textContent
çã®ãã¤ãã£ããã©ã¦ã¶ API ã使ç¨ãã¦è¡ãããããããã©ã¦ã¶èªä½ãèå¼±ãªå ´åã®ã¿èå¼±æ§ãåå¨ãã¾ãã
å±æ§ã®ãã¤ã³ãã£ã³ã°
åæ§ã«ãåçãªå±æ§ã®ãã¤ã³ãã£ã³ã°ãèªåã§ã¨ã¹ã±ã¼ãå¦çãããã¾ããä¾ãã°ãã®ãããªãã³ãã¬ã¼ãã®å ´å:
<h1 v-bind:title="userProvidedString">
hello
</h1>
ãã userProvidedString
ã«ä»¥ä¸ãå«ã¾ãã¦ããã¨:
'" onclick="alert(\'hi\')'
以ä¸ã®ããã«ã¨ã¹ã±ã¼ãããã HTML ã«ãªãã¾ãã
" onclick="alert('hi')
ãã®ããã«ãtitle
å±æ§ã«ä»»æã® HTML ãã¤ã³ã¸ã§ã¯ãããããã¨ãé²ãã¾ãããã®ã¨ã¹ã±ã¼ãå¦çã setAttribute
çã®ãã¤ãã£ããã©ã¦ã¶ API ã使ç¨ãã¦è¡ãããããããã©ã¦ã¶èªä½ãèå¼±ãªå ´åã®ã¿èå¼±æ§ãåå¨ãã¾ãã
æ½å¨çãªå±éº
ã©ã®ãã㪠Web ã¢ããªã±ã¼ã·ã§ã³ã§ããã¦ã¼ã¶ã®å ¥åã«ããç¡å®³å (sanitize)ããã¦ããªãã³ã³ãã³ãã HTMLãCSSãJavaScript ã¨ãã¦å®è¡ã§ããããã«ãããã¨ã¯æ½å¨çãªå±éºããããããå¯è½ãªéãé¿ããå¿ è¦ãããã¾ããããããªãããããç¨åº¦ã®ãªã¹ã¯ãªã許容ãããå ´åãããã¾ãã
ä¾ãã°ãCodePen ã JSFiddle ãªã©ã®ãµã¼ãã¹ã§ã¯ãã¦ã¼ã¶ã«ãã£ã¦å ¥åãããã³ã³ãã³ããå®è¡ã§ãã¾ããããããããã¯æ³å®éãã§ãiframe å ã§ããç¨åº¦ãµã³ãããã¯ã¹åããã¦ããç¶æ³ã«ããã¦ã§ããéè¦ãªæ©è½ãæ¬è³ªçã«ããç¨åº¦ã®èå¼±æ§ãå¿ è¦ã¨ããå ´åããã®æ©è½ã®éè¦æ§ã¨èå¼±æ§ã«ããææªã®ã·ããªãªã¨ãã¦ãã³ãã«ããããã¨ã¯ãããªãã®ãã¼ã ã«å§ãããã¾ãã
HTML ã®æ¿å ¥
åè¿°ã®éããVue ã§ã¯ HTML ã³ã³ãã³ããèªåã§ã¨ã¹ã±ã¼ãå¦çãã誤ã£ã¦å®è¡å¯è½ãª HTML ãã¢ããªã±ã¼ã·ã§ã³å ã«æ¿å ¥ãããã¨ãé²ãã§ãã¾ãã
ãã ããHTML ãå®å ¨ãªãã¨ãäºåã«ããã£ã¦ããå ´åã¯æ示çã«ãããã¬ã³ããªã³ã°ãããã¨ãå¯è½ã§ã:
ãã³ãã¬ã¼ããå©ç¨ããå ´å:
<div v-html="userProvidedHtml"></div>
æç»é¢æ°ãå©ç¨ããå ´å:
h('div', { domProps: { innerHTML: this.userProvidedHtml } })
JSX ã«ããæç»é¢æ°ãå©ç¨ããå ´å:
<div domPropsInnerHTML={this.userProvidedHtml}></div>
ã¦ã¼ã¶ãå ¥åãã HTML ã¯ããµã³ãããã¯ã¹åããã iframeãã¾ãã¯ãããå ¥åããã¦ã¼ã¶ã®ã¿ãã¢ã¯ã»ã¹ã§ããã¢ããªã®ä¸é¨ã¨ããå ´åãé¤ãã100%å®å ¨ã¨ã¯ã¿ãªãããªããã¨ã«æ³¨æãã¦ä¸ãããã¾ããã¦ã¼ã¶ãç¬èªã® Vue ãã³ãã¬ã¼ããä½æã§ããããã«ãããã¨ãåæ§ã®å±éºãããã¾ãã
URL ã®æ¿å ¥
ãã®ãã㪠URL ã®å ´å:
<a v-bind:href="userProvidedUrl">
click me
</a>
URL ã âç¡å®³å (sanitize)â ã㦠javascript: ã®å©ç¨ã«ãã JavaScript å®è¡ãé²ãã§ããªãå ´åãæ½å¨çãªã»ãã¥ãªãã£ã®åé¡ãããã¾ããããã®å¯¾çã«ãsanitize-url çã®ã©ã¤ãã©ãªãããã¾ããããã注æãã¦ãã ãã:
ããã³ãã¨ã³ã㧠URL ã®ç¡å®³å (sanitize)å¦çãè¡ã£ããã¨ãããå ´åãããã¯ãã§ã«ã»ãã¥ãªãã£ä¸ã®åé¡ãã¯ããã§ãã¾ããã¦ã¼ã¶ã®å ¥åã«ãã URL ã¯ã常ã«ããã¯ã¨ã³ãã§ãã¼ã¿ãã¼ã¹ã«ä¿åããåã®å¦çãå¿ è¦ã§ãããããããã¨ã§ã¢ãã¤ã«ã®ãã¤ãã£ãã¢ããªãå«ããAPI ã«æ¥ç¶ãããã¹ã¦ã®ã¯ã©ã¤ã¢ã³ãã§åé¡ãåé¿ãããã¨ãã§ãã¾ããã¾ããç¡å®³å (sanitize)å¦çãããã URL ã ã¨ãã¦ããVue ã¯ãªã³ã¯å ã®å®å ¨æ§ãä¿è¨¼ãããã¨ã¯ã§ãã¾ããã
ã¹ã¿ã¤ã«ã®æ¿å ¥
ãã®ä¾ãè¦ã¦ãã ãã:
<a
v-bind:href="sanitizedUrl"
v-bind:style="userProvidedStyles"
>
click me
</a>
sanitizedUrl
ã¯ç¡å®³å (sanitize)ããã¦ããã¨ä»®å®ãã¾ãããã ããã¯ç´ãããªãå®éã® URL ã§ãJavaScript ã§ã¯ããã¾ãããuserProvidedStyles
ãå©ç¨ããã¨ãæªæã®ããã¦ã¼ã¶ã¯âã¯ãªãã¯ã¸ã£ãã¯âã®ããã® CSS ãè¨ç½®ã§ãã¾ããä¾ãã°ããã°ã¤ã³ãã¿ã³ã®ä¸ã®éæããã¯ã¹ã«ãªã³ã¯ãã¹ã¿ã¤ãªã³ã°ãã¾ããããã¦ããã°ã¤ã³ãã¼ã¸ã«ä¼¼ãã https://user-controlled-website.com/
ã¨ãããµã¤ããæ§ç¯ããã¦ããå ´åãã¦ã¼ã¶ã¼ã¯ãã°ã¤ã³æ
å ±ãçã¾ãã¦ãã¾ãããããã¾ããã
<style>
è¦ç´ ã«å¯¾ãã¦ã¦ã¼ã¶ã®å
¥åããã³ã³ãã³ãã許å¯ãã¦ãã¾ãã¨ãæ´ã«å¤§ããªèå¼±æ§ãçºçãããã®ãã¼ã¸å
¨ä½ã®ã¹ã¿ã¤ã«ãå¶å¾¡ããã¦ãã¾ãã¨ãããã¨ãæ³åã§ããã§ãããããã®ããã«ãVue ã§ã¯ä»¥ä¸ã®ãããªãã³ãã¬ã¼ãå
ã§ã®ã¹ã¿ã¤ã«ã¿ã°ã®ã¬ã³ããªã³ã°ã¯ãããã¹ãã§ã:
<style>{{ userProvidedStyles }}</style>
ã¦ã¼ã¶ã«ããã¯ãªãã¯ã¸ã£ãã¯ãå®å ¨ã«é²æ¢ããããã«ã¯ãCSS ã®å®å ¨ãªå¶å¾¡ã¯ iframe å ã®ãµã³ãããã¯ã¹åãããå ´æã§ã®ã¿è¡ããã¨ããå§ããã¾ããã¾ãã¯ãã¹ã¿ã¤ã«ãã¤ã³ãã£ã³ã°ãä»ãã¦ã¦ã¼ã¶ã«å¶å¾¡ãä¸ãããå ´åã¯ããªãã¸ã§ã¯ãæ§æ ãå©ç¨ããç¹å®ã®ããããã£ã®å¤ã ããè¨å®ã§ããããã«ãããã¨ããå§ããã¾ãããã®ä¾ã®ããã«:
<a
v-bind:href="sanitizedUrl"
v-bind:style="{
color: userProvidedColor,
background: userProvidedBackground
}"
>
click me
</a>
JavaScript ã®æ¿å ¥
ãã³ãã¬ã¼ãã¨æç»é¢æ°ã¯å¯ä½ç¨ããã¤ã¹ãã§ã¯ãªããããVue 㧠<script>
è¦ç´ ãã¬ã³ããªã³ã°ãããã¨ã¯å¼·ããå§ããã¾ããããã ãããã¯ãå®è¡æã« JavaScript ã¨ãã¦è©ä¾¡ãããæååãå«ããããã®å¯ä¸ã®æ¹æ³ã§ã¯ããã¾ããã
ãã¹ã¦ã® HTML è¦ç´ ã«ã¯ãonclick
ã onfocus
ãonmouseenter
ãªã©ã® JavaScript æååãå¤ã¨ãã¦åãå
¥ããå±æ§ãããã¾ããã¦ã¼ã¶ã«ãã£ã¦å
¥åããã JavaScript ããããã®ã¤ãã³ãå±æ§ã«ãã¤ã³ããããã¨ã¯ãæ½å¨çãªã»ãã¥ãªãã£ãªã¹ã¯ã¨ãªãã®ã§é¿ããå¿
è¦ãããã¾ãã
ã¦ã¼ã¶ãå ¥åãã JavaScript ã¯ããµã³ãããã¯ã¹åããã iframeãã¾ãã¯ãããå ¥åããã¦ã¼ã¶ã®ã¿ãã¢ã¯ã»ã¹ã§ããã¢ããªã®ä¸é¨ã¨ããå ´åãé¤ãã100%å®å ¨ã¨ã¯ã¿ãªãããªããã¨ã«æ³¨æãã¦ãã ããã
Vue ãã³ãã¬ã¼ãã§ã®ã¯ãã¹ãµã¤ãã¹ã¯ãªããã£ã³ã° (XSS) ãå®è¡ããæ¹æ³ã«ã¤ãã¦ãèå¼±æ§ã¬ãã¼ããåãåããã¨ãææããã¾ããä¸è¬çã«ãXSS ã許å¯ãã以ä¸ã®2ã¤ã®ä¾ããéçºè ãä¿è·ããå®ç¨çãªæ¹æ³ã¯ç¡ãããããã®ãããªå ´åã¯èå¼±æ§ã¨ã¯è¦ãªãã¾ããã
éçºè ããã¦ã¼ã¶å ¥åã«ããç¡å®³å (sanitize)ããã¦ããªãã³ã³ãã³ãã Vue ãã³ãã¬ã¼ãã¨ãã¦ã¬ã³ããªã³ã°ããããã«æ示çã«æ示ãã¦ããå ´åãããã¯æ¬è³ªçã«å®å ¨ã§ã¯ãªããã¾ã Vue ããã®ãªãªã¸ãã«ã®ã³ã³ãã³ããç¥ãæ¹æ³ã¯ããã¾ããã
éçºè ãããµã¼ãã§ã¬ã³ããªã³ã°ãããã¦ã¼ã¶å ¥åã®ã³ã³ãã³ããå«ã HTML ãã¼ã¸å ¨ä½ã« Vue ããã¦ã³ããã¦ããå ´åãåé¡ã¯åºæ¬çã«#1ã¨åãã§ãããéçºè ãæ°ã¥ãã¬ãã¡ã«ãããã¦ãã¾ããã¨ãããã¾ããããã«ããããã¬ã¼ã³ãª HTML ã¨ãã¦ã¯ç¡å®³ã ã¨ãã¦ããVue ãã³ãã¬ã¼ãã¨ãã¦ã¯å®å ¨ã§ãªã HTML ãæ»æè ãè¨ç½®ãããã¨ã§ããèå¼±æ§ãçºçãã¾ãããã¹ããã©ã¯ãã£ã¹ã¯ããµã¼ãã¼ã§ã¬ã³ããªã³ã°ãããã¦ã¼ã¶ã¼å ¥åã®ã³ã³ãã³ã (user-provided content)è¦ç´ ã« Vue ããã¦ã³ãããªããã¨ã§ãã
ãã¹ããã©ã¯ãã£ã¹
ä¸è¬çãªã«ã¼ã«ã¨ãã¦ãç¡å®³å (sanitize)ããã¦ããªãã¦ã¼ã¶ã¼å ¥åã®ã³ã³ãã³ã (user-provided content)ï¼HTMLãCSSãJavaScriptï¼ãå®è¡ãããã¨ã¯ãæ»æã«ãããããå¯è½æ§ãããã¨ãããã¨ã§ãããã®ã¢ããã¤ã¹ã¯ Vue ã«éãããä»ã®ãã¬ã¼ã ã¯ã¼ã¯ãããã«ã¯ãã¬ã¼ã ã¯ã¼ã¯ãå©ç¨ãã¦ããªãå ´åã§ãæå¹ã§ãã
æ½å¨çãªå±éºã®æ¨å¥¨äºé ã«å ãã以ä¸ã®ãªã½ã¼ã¹ãçç¥ãã¦ãããã¨ããå§ããã¾ãã
DOM ã¸æç»ãããããªãµã¼ããã¼ãã£è£½ã®ã³ã³ãã¼ãã³ãã使ç¨ããå ´åã¯ãå ã«å¦ãã å 容ãå©ç¨ãã¦ä¾åããã½ã¼ã¹ã³ã¼ãã®æ½å¨çãªå±éºãã¿ã¼ã³ã«ã¤ãã¦ãã§ãã¯ãã¦ãã ããã
ããã¯ã¨ã³ãã¨ã®èª¿æ´
ã¯ãã¹ãµã¤ãã»ãªã¯ã¨ã¹ããã©ã¼ã¸ã§ãª ( CSRF / XSRF ) ã ã¯ãã¹ãµã¤ãã»ã¹ã¯ãªããã¤ã³ã¯ã«ã¼ã¸ã§ã³ ( XSSI ) ãªã©ã® HTTP ã®èå¼±æ§ã¯ã主ã«ããã¯ã¨ã³ãå´ã§å¯¾å¦ããããããVue ã§æ°ã«ããå¿ è¦ã¯ããã¾ãããã§ãããããã¯ã¨ã³ããã¼ã ã¨é£æºãåããAPI ã¨ã®æé©ãªå¯¾è©±æ¹æ³ (ä¾ãã°ãã©ã¼ã éä¿¡æã« CSRF ãã¼ã¯ã³ãéä¿¡ããããªã©) ãå¦ã¶ãã¨ããå§ããã¾ãã
ãµã¼ãã¼ãµã¤ãã¬ã³ããªã³ã° (SSR)
SSR ãå©ç¨ããå ´åãä¸è¨ã®æ¨å¥¨äºé ã«å ãã¦ããã¤ãã»ãã¥ãªãã£ä¸ã®æ¸å¿µãããã¾ããå¥éãVue.js ãµã¼ããµã¤ãã¬ã³ããªã³ã°ã¬ã¤ã ã§è§£èª¬ããã¦ãããã¹ããã©ã¯ãã£ã¹ãåç §ãã¦ãã ããã