web-dev-qa-db-ja.com

Chromeオートフィル/オートコンプリートパスワードの値なし

いくつかのサイトのユーザー名とパスワードを保存すると、Chromeはそのユーザー名とパスワードを自動入力しますが、パスワード入力フィールドの値を取得しようとすると、そこに値があっても空の文字列になります******。

ページのどこかをクリックすると、input type="password"が入力されます。

これはFiddle ser/pass htmlおよびconsole.logコマンド。ここでは表示できませんが、ログインフォームがあるすべてのページで再現でき、ページの読み込み時にユーザー名とパスワードが自動入力されます。サイトの他の場所をクリックする前にフィールドの値を調べると、空の文字列になります。

これは、FirefoxやInternet Explorerの場合ではなく、input要素の値にパスワードを入力します。

Windows 7 Ultimate 64ビットOSとGoogleを使用していますChromeバージョンは48.0.2564.97 m

これは通常の動作ですか、バグですか?

UPDATE:

F5をクリックしてページをリロードし、パスワードフィールドを調べると、パスワードの値が表示されます。左上にあるChromeのリロードボタンをクリックすると、パスワードフィールドの値は空の文字列になります。

49
onetwo12

これはChromeのバグのようです。 Chrome初期ページの読み込み時にパスワードを自動入力する(ただし、更新ではない))の場合、値は画面上のフォームフィールドに表示されますが、JavascriptのpasswordField.valueを照会すると空の文字列。Javascriptでその値を見ることに依存している場合、そうすることはできません。ユーザーがページ上の任意の場所をクリックするなど、ページで他のアクションを実行すると、値が突然JavaScriptに表示されます。

これがバグかどうか、または隠しフレームがパスワードを盗むのを防ぐなど、これを行うためのセキュリティ上の理由があるかどうか、私は実際に100%確信していません。

使用した回避策は、Chrome=が自動入力されたフィールドに対して行う背景色の変更を検出することです。Chrome auto- Javascriptでこれを検出すると、Javascriptで値が空白として表示されていても、フィールドに値が自動入力されたことを知ることができます。ケースでは、パスワードフィールドに何かを入力するまで送信ボタンが有効にならないログインフォームがあり、値または自動入力background-colorのいずれかを検出することで、フィールドに何かがあると判断できます。送信ボタンを有効にすると、ボタンをクリックする(またはEnterキーを押す)とすぐにパスワードフィールドの値がJavascriptに表示されます。これは、ページとのやり取りにより問題が修正されるため、そこから通常どおり続行できます。

38
Adam Hamilton

2016年7月8日現在の回答

アダムが正しく述べた これはバグ(または意図した動作)です。ただし、これまでの回答のどれも実際にこれを修正する方法を示していないため、ここではChromeを使用してオートコンプリートされた値を実際の値として処理する方法があります。

いくつかのことを順番に行う必要があり、これはFirefoxでなくChromeで実行する必要があるため、ifです。

まず、要素に注目します。次に、新しいTextEventを作成し、initTextEventを実行します。これにより、指定したカスタム文字列( "@@@@@"を使用)が値の先頭に追加されます。これはChromeをトリガーし、実際に値が本物のように振る舞います。その後、追加したカスタム文字列を削除して、フォーカスを外します。


コード:

input.focus();

var event = document.createEvent('TextEvent');

if ( event.initTextEvent ) {

    event.initTextEvent('textInput', true, true, window, '@@@@@');

    input.dispatchEvent(event);

    input.value = input.value.replace('@@@@@','');

}

input.blur();

2016年8月10日編集

これはChromeではWindowsとAndroidでのみ動作します。OSXでは動作しません。さらに、2016年9月には動作しなくなります。

https://www.chromestatus.com/features/57188​​03933560832

また、Chromiumチケットを開きました。

https://bugs.chromium.org/p/chromium/issues/detail?id=636425

8月12日の時点で、Chromeチームのメンバーは、上記のチケットで、バグと見なさないため、動作は変更されないだろうと述べました。

長期的な回避策の提案:

ただし、現在の動作は、最初に実装されたときから微調整されています。ユーザーは、報告される値のためにパスワード入力を操作する必要がなくなりました。ユーザーは、ページの任意の部分と対話する(マウスまたはキーボードイベントを送信する)だけで済みます。つまり、ページロードで検証を実行しても、送信ボタンをクリックすると、Chrome=がパスワード値を正しく報告します。次善策は、それがあなたがやろうとしているのであれば、送信時にオートコンプリートされる可能性があります。


2016年12月13日の編集:

新しいChromiumチケットがオープンされ、より良い受け取りが行われています。 Chromeのこの動作を変更することに興味がある場合は、この新しいチケットにスターを付けてください。

https://bugs.chromium.org/p/chromium/issues/detail?id=669724

23
Andy Mercer

Andy Mercerが言った から続けて、ここに私の回避策があります。多くの人のように、実際のパスワード値は必要ありません。適切な検証メッセージを表示できるように、パスワードボックスが自動入力されたことを知る必要があります。

個人的には、Chromeのオートフィルによる背景色の変化の原因を検出するための推奨ソリューションは使用しません。そのアプローチはもろいようです。黄色が変わらないことに依存します。しかし、それは拡張機能によって変更され、別のBlinkベースのブラウザ(Operaなど)では異なる可能性があります。さらに、今後Googleが別の色を使用しないという約束はありません。私の方法はスタイルに関係なく機能します。

まず、CSSで-webkit-autofil疑似クラスが適用されるときにINPUTのコンテンツを設定します。

input:-webkit-autofill {
  content: "\feff"
}

次に、設定するコンテンツをチェックするルーチンを作成しました。

const autofillContent = `"${String.fromCharCode(0xFEFF)}"`;
function checkAutofill(input) {
    if (!input.value) {
        const style = window.getComputedStyle(input);
        if (style.content !== autofillContent)
            return false;
    }

    //the autofill was detected
    input.classList.add('valid'); //replace this. do want you want to the input
    return true;
}

最後に、inputをポーリングして、自動入力時間を完了できるようにしました。

const input = document.querySelector("input[type=password]");

if (!checkAutofill(input)) {
    let interval = 0;
    const intervalId = setInterval(() => {
        if (checkAutofill(input) || interval++ >= 20)
            clearInterval(intervalId);
    }, 100);
}
8
Ben

この問題に対する私の解決策は次のとおりです。

$(document).ready(function(){
  if ( $("input:-webkit-autofill").length ){
    $(".error").text("Chrome autofill detected. Please click anywhere.");
  }
});

$(document).click(function(){
  $(".error").text("");
});

基本的に、クリックすると入力がユーザーに表示されるので、クリックするようにユーザーに依頼し、クリックするとメッセージを非表示にします。

最もエレガントなソリューションではありませんが、おそらく最速です。

5
SamJakob

12月16日時点の別のオプション/ Chrome 54

パスワードフィールドの値を取得できませんが、「しばらく」後にパスワードを選択することでパスワードの長さを取得できます。これは、送信ボタンを有効にするのに十分です。

setTimeout(function() {
  // get the password field
  var pwd = document.getElementById('pwd');
  pwd.focus();
  pwd.select();
  var noChars = pwd.selectionEnd;
  // move focus to username field for first-time visitors
  document.getElementById('username').focus()
  if (noChars > 0) {
    document.getElementById('loginBtn').disabled = false;
  }
}, 100);
4
crsw

Adamが指定した回避策:

... Chrome=自動入力されたフィールドに対して行われる背景色の変更を検出します。Chrome自動入力されたフィールドの背景を黄色に色付けし、 Javascriptでこれを検出すると、Javascriptで値が空白として表示されていても、フィールドに値が自動入力されたことがわかります。

私はこれが好きでした:-

getComputedStyle(element).backgroundColor === "rgb(250, 255, 189)"

ここで、rgb(250、255、189)は黄色Chromeは自動入力に適用されます。

4
Frozen Crayon

少なくとも私の目的には有効なこの問題の解決策を見つけました。

ログインフォームがあり、ロードしたらすぐにEnterキーを押したいのですが、Chromeでパスワードの空白の問題が発生していました。

次のように動作しているようで、最初のEnterキーが失敗し、もう一度再試行するChromeが起動し、パスワード値を提供します。

$(function(){

    // bind form submit loginOnSubmit
    $('#loginForm').submit(loginOnSubmit);

    // submit form when enter pressed on username or password inputs
    $('#username,#password').keydown(function(e) {
        if (e.keyCode == 13) {
            $('#loginForm').submit(e);
            return false;
        }
    });

});

function loginOnSubmit(e, passwordRetry) {

    // on submit check if password is blank, if so run this again in 100 milliseconds
    // passwordRetry flag prevents an infinite loop
    if(password.value == "" && passwordRetry != true)
    {
        setTimeout(function(){loginOnSubmit(e,true);},100);
        return false;
    }

    // login logic here
}
3
bbeckford

これに関連するangularディレクティブを記述しました。次のコードで終わりました。

if ('password' == $attrs.type) {
      const _interval = $interval(() => { //interval required, chrome takes some time to autofill
          if ($element.is(':-webkit-autofill')) { //jQuery.is()
              //your code
              $interval.cancel(_interval);
          }
      }, 500, 10); //0.5s, 10 times
}

ps:100%の時間を検出することはありません。chrome入力を埋めるのに5秒以上かかる場合があります。

3
Ian
$element.is("*:-webkit-autofill")

私のために働く

2
harry

Chromeの意図した動作は、ユーザーが何らかの方法でフレームを操作するまで、DOMに自動入力されたパスワードの空のvalueがあり、その時点でchromeが実際に値を設定するこの時点まで、クライアント側の検証またはajax送信の試行では、パスワードが空として表示されます。

この「フレームインタラクションでのパスワード値の入力」動作には一貫性がありません。フォームが同じ元のiframeでホストされている場合、最初の読み込みでのみ動作し、それ以降の読み込みでは動作しないことがわかりました。

これは、最初のロード時に自動補完パスワードが入力されるajaxフォームで最も顕著ですが、そのパスワードが無効でajax送信がフォームDOMを再レンダリングする場合、自動補完パスワードは視覚的に再表示されますが、valueは決してありませんインタラクションに関係なく入力されます。

このシナリオでは、blurまたはinputイベントのトリガーなど、言及された回避策は機能しませんでした。私が見つけた唯一の回避策は、ajaxプロセスがフォームを再レンダリングした後にパスワードフィールドの値をリセットすることです、例えば:

$('input[type="password"]').val("");

上記の後、Chromeは実際にパスワードを再度オートコンプリートしますが、valueは実際に入力されます。

現在のユースケースでは、ASP.NETのAjax.BeginFormを使用し、AjaxOptions.OnSuccessコールバックで上記の回避策を使用しています。

1
James Martin

Angularでは、Chrome(ユーザーがページを操作した後にのみ自動入力値の読み取りを許可)の新しい動作は、特定のシナリオでAngularの検証機能を使用している場合に問題として現れます。 (たとえば、フォームで標準のメソッド/アクション属性を使用する場合など)。送信ハンドラはすぐに実行されるため、フォーム検証ツールはChromeから自動入力された値をキャプチャできません。

フォームコントローラーを明示的に呼び出すために私が見つけた解決策$commitViewValueチェックする前に再検証をトリガーする送信ハンドラーの関数form.$valid または form.invalidなど.

例:

function submit ($event) {
    // Allow model to be updated by Chrome autofill
    // @see http://stackoverflow.com/questions/35049555/chrome-autofill-autocomplete-no-value-for-password
    $scope.loginModule.$commitViewValue();

    if ($scope.loginModule.$invalid) {
        // Disallow login
        $scope.loginModule.$submitted = true;
        $event.preventDefault();
    } else {
        // Allow login
    }
}

これはこれまでのところ私たちのために働いていますが、誰かが問題のために別の、よりエレガントな回避策を見つけたら非常に興味があります。

1
drewzh

バグではありません。これはセキュリティの問題です。ユーザーが確認することなく、JavaScriptを使用して自動入力パスワードを取得できるとしたらどうでしょう。

0
Timothy Law

オートコンプリート属性を、ユーザー名フィールドのユーザー名とパスワードフィールドの新しいパスワードに設定するだけです。

<input type="text" id="username" autocomplete="username">
<input type="password" id="password" autocomplete="new-password" >
0
Joseph

オートコンプリート機能は正常に無効になりました。 動作します!

[HTML]

<div id="login_screen" style="min-height: 45px;">
   <input id="password_1" type="text" name="password">
</div>

[JQuery]

$("#login_screen").on('keyup keydown mousedown', '#password_1', function (e) {
    let elem = $(this);

    if (elem.val().length > 0 && elem.attr("type") === "text") {
        elem.attr("type", "password");
    } else {
        setTimeout(function () {
            if (elem.val().length === 0) {
                elem.attr("type", "text");
                elem.hide();
                setTimeout(function () {
                    elem.show().focus();
                }, 1);
            }
        }, 1);
    }

    if (elem.val() === "" && e.type === "mousedown") {
        elem.hide();
        setTimeout(function () {
            elem.show().focus();
        }, 1);
    }

});
0
EngineerCoder
var txtInput = $(sTxt);
txtInput.focus();
txtInput.select();

私の場合、このソリューションは有効でした。 jQuery 3.1.1を使用します。

0
CornyVanBeck

私には、この解決策のどれもうまくいかないようでした。

CSSスタイリングに使用する場合は、次のように-webkit-autofillプロパティを使用する必要があることに言及する価値があると思います。

input:-webkit-autofill~.label,
input:-webkit-autofill:hover~.label, 
input:-webkit-autofill:focus~.label
input:focus~.label,
input:not(.empty)~.label {
  top: -12px;
  font-size: 12px;
  color: rgba(0, 0, 0, .4);
  font-weight: 600
}

0
Adrian Gołda

入力が満たされていると見なされるようにするには、その上でblurをトリガーしてみてください:$('input[type="password"]').blur();

0
gregmatys