Запрещаем браузеру Google Chrome сохранять и предлагать сохраненный пароль в нашем приложении на Vue.js(v2)

—

от автора

Мир стоит вверх ногами. Корпорация добра печется о нашей безопасности. И в то же время делает все, чтобы наши секреты стали достоянием гласности. Это я о политике гугл в плане сохранения логин-паролей в браузере, через него в аккаунте и о доступности всего нашего секретного добра всем, кто сможет подойти к нашим компьютерам.

Да, удобно. Но небезопасно. И временами очень вредно.

Запустил я очередной проект на работе. И самой большой проблемой по опыту старого проекта было то, что сотрудники вовсю пользовались автосохраненим паролей, поэтому под Васей мог сидеть Сергей и ни о какой нормальной аутентификации, а тем более разраничении прав доступа речи идти не могло.

Сначала двинулся в сторону того же гугла — как отключить или запретить автосохранение или автоподстановку сохраненного пароля? Старые рецепты с autocomplete="off" и autocomplete="new-password" уже не работают, последний работающий рецепт оказался прост — головную боль следует лечить усекновением болящей. То есть глобальным отключением автосохранения. Но это не вариант. Пусть юзеры дальше балуются своими паролями от почты, соцсетей и прочих радостей жизни, мне не жалко.

Далее последовал легкий инжиниринг. И вот какой результат — если на страничке есть input type="password", то при появлении первого символа в адресной строке появляется ключик. И все. Что ты ни делай, какие html тэги ни прописывай — есть password, значит, надо бежать и барину кланяться, предлагая все мыслимые и немыслимые блага от того, что барин позволит сохранить пароль. Ну и потом барин будет весьма доволен, что пароль не надо вспоминать, а просто его вставить.

Хмм… подумал я… И решил — раз у хрома такая нервная реакция на type="password", то надо просто от него отказаться и всех делов то!

Сказано — сделано. Изваял компонент, который незамысловато делает простейшую вещь — на экран выводит точечки, а в v-model передает то, что введено. Ну и плюсом отрабатывает клавишу Enter.

Конечно, не обошлось без ограничений. Но они очень малы и незначительны — нельзя курсор перемещать стрелками, только backspace. Но, учитывая, что под точками и так не видно, где и что надо подправить — вероятность испытать колоссальное неудобство от такого ограничения стремится к нулю. Не стал делать кнопочку с глазиком, чтобы посмотреть, что же я ввел, label для input оформил в стиле компонента vuetify, то есть текст-подсказка уползает вверх при фокусе и возвращается при утере фокуса при условии, что ничего не было введено.

Ну и использование такого компонента тоже очень простое — создать .vue файл, импортировать в проект и использовать в шаблоне.

Теперь, собственно, код.

Код под спойлером
<template>     <div class="logpass">         <input type="hidden" v-model="opass">         <label :for="inpid">Пароль</label>         <input style="width: 100%"                :id="inpid"                type="text"                v-model="ipass"                @input="input"                @keydown="keyDown"                @focus="focus"                @blur="blur"                @keydown.enter="$emit('keydown_enter',$event)">     </div> </template>  <script>     export default {         name: "login-password",         data() {             return {                 ipass:'', // input password                 opass:'', // output password             }         },         computed: {             inpid(){                 let length=7                 let result                 let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';                 let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';                 let el=''                 while(el!==null){ // void to duplicate id if node with same id exists                     result=letters.charAt(Math.floor(Math.random() *                         letters.length));                     for (let i = 0; i < length; i++) {                         result += characters.charAt(Math.floor(Math.random() *                             characters.length));                     }                     el=document.querySelector('#'+result)                 }                 return result;             },         },         methods: {             focus(event){                 let el=document.querySelector(['label[for="'+event.target.id+'"]'])                 if(el){                     el.classList.add('label-active')                 }             },             blur(event){                 let el=document.querySelector(['label[for="'+event.target.id+'"]'])                 if(el && this.opass==''){                     el.classList.remove('label-active')                 }             },             input(event){                 if(this.opass.length<this.ipass.length){                     let s = this.ipass.slice(-1)                     this.opass=''.concat(this.opass,s)                     s = ''                     for(let i=0;i<this.ipass.length;i++)s=''.concat(s,'•')                     this.ipass=s                     this.$emit('input',this.opass)                 }else{                     if(this.opass.length>this.ipass.length){                         this.opass=this.opass.slice(0,this.ipass.length)                         this.$emit('input',this.opass)                     }                 }             },             keyDown(event){                 if(event.key=='ArrowLeft'||event.key=='ArrowRight'||event.key=='ArrowUp'||event.key=='ArrowDown'){                     event.preventDefault()                 }             },         },     } </script>  <style scoped lang="scss"> .logpass{     padding-top:14px;     padding-bottom: 12px;     display: flex;     & label{         padding: 5px;         position: absolute;         color: #999;         transition: .3s cubic-bezier(.25,.8,.5,1);     }     & .label-active{         font-size: 10px;         margin-top: -20px;         margin-left: -5px;     } } </style> 

Как видим — достаточно простая логика — при вводе очередного символа он заменяется на точку и дублируется в переменную, переданную в v-model. Именно запрет на перемещение курсора в поле ввода позволил реализацию такой логики.

Еще одно замечание — этот компонент не использует инициализацию значением, которое, возможно уже было в v-model-переменной.

Пример использования:

// какой-нибудь наш модуль на vue, в котором необходим ввод пароля <template> <div>     логин: <input type="text" v-model="mylogin">     <login-password v-model="mypassword" @keydown_enter="makeLogin">     </login-password>   </div> </template> <script>     export default {         name: "Login",         data() {             return {                 mylogin: '',                 mypassword:''             }         },         components: {             LoginPassword:()=>import('./login-password')         },             methods:{           makeLogn(){             .....           }           .......                         

Ну и напоследок — код свободный, берите, кто хотите, возможно, кому-то идея подойдет на React или Angular.


ссылка на оригинал статьи https://habr.com/ru/articles/589481/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *