差異處
這裏顯示兩個版本的差異處。
java:web:wicket:dont_autocomplete [2018/11/09 18:17] tony |
java:web:wicket:dont_autocomplete [2023/06/25 09:48] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | {{tag>wicket autocomplete password}} | ||
- | ====== Wicket - Don't autocomplete ====== | ||
- | ===== Problem ===== | ||
- | 瀏覽器的貼心有時會為開發人員帶來困擾:\\ | ||
- | {{:java:web:wicket:remember_login_sample.png|}}\\ | ||
- | \\ | ||
- | 相信這個畫面大家並不陌生,登入facebook、mail都會跳這個dialog;在你下次登入時,瀏覽器會自動幫你輸入帳號密碼。當你做的軟體有整合LDAP、AD、SMTP、Samba任何與帳號密碼有關的功能時,使用者會想遇到這樣的狀況嗎?\\ | ||
- | {{:java:web:wicket:autocomplete_sample.png|}}\\ | ||
- | \\ | ||
- | 假如我根本不需要使用帳號密碼,你幫我填入我不是還要自己消掉嗎? 除此之外,在Submit後所跳出的對話盒,是另一個困擾。本篇文章會分享針對這兩個問題的治療經驗。 | ||
- | ===== How to prevent the autocomplete? ===== | ||
- | 我撰寫此篇文章時,測試的瀏覽器分別為以下版本: | ||
- | * Chrome: 70.0.3538.77 | ||
- | * Firefox: 63.0.1 | ||
- | * IE: 11.0.9600.19129 | ||
- | 分享的方法是給大家參考,最後要使用哪種就看應用程式需求。 | ||
- | ==== Don't use type="password" ==== | ||
- | 要一次解決以上兩個問題,就是不要使用password。目前看到唯一跨瀏覽器的方法,可以使用這個GitHub上MIT license的project: [[https://github.com/noppa/text-security|text-security]];它是透過css去模擬密碼的外表,可以直接看[[https://jsfiddle.net/449Lamue/6/|demo]]。 | ||
- | ==== Declare field as Readonly ==== | ||
- | 這個做法是為了解決autocomplete的問題。原理就是將password field設定為readonly,而瀏覽器針對有值或者readonly的password不會自動填入,最後再透過onfocus將readonly屬性移除就可以正常使用: | ||
- | <code html> | ||
- | <input type="password" readonly | ||
- | onfocus="this.removeAttribute('readonly');this.select(); this.selectionStart = this.selectionEnd = this.value.length;"/> | ||
- | </code> | ||
- | 在IE上如果僅移除readonly屬性,會造成點擊兩次才能夠輸入密碼的問題;必須透過再次選取與調整游標位置去讓使用者無痛。最後我們有使用這方法,主要是由於我們使用Apache Wicket,這種方式比較容易做成可重複使用的元件。 | ||
- | ==== Apply autocomplete="nope" or autocomplete="off" ==== | ||
- | 這方法不推薦使用。目前我知道autocomplete="off"可以使用於IE,但autocomplete="nope"只能用於chrome與firefox的某些版本。 | ||
- | ==== Fake blank input field ==== | ||
- | 這個做法是在form的前面塞入隱藏的欄位給瀏覽器做自動完成。最早我們使用這個方法,但它有以下缺點: | ||
- | - 如果整合的系統相當多,你會產生許多duplicated code。 | ||
- | - 在form submit之後,如果你的real-username與瀏覽器記住的username不同,所彈出記住登入資訊的帳號,會讓使用者覺得這是個bug。 | ||
- | - 在firexo 63以後的版本依然會有自動完成的現象;也是這個原因導致我們花時間研究這個問題。 | ||
- | <code html> | ||
- | <form autocomplete="off"> | ||
- | <input id="username" style="display:none" type="text" name="fakeusernameremembered"> | ||
- | <input id="password" style="display:none" type="password" name="fakepasswordremembered"> | ||
- | <input id="real-username" type="text" autocomplete="nope"> | ||
- | <input id="real-password" type="password" autocomplete="new-password"> | ||
- | </form> | ||
- | </code> | ||
- | (範例程式出自於[[https://gist.github.com/runspired/b9fdf1fa74fc9fb4554418dea35718fe|link]]) | ||
- | ===== How to prevent the browser show remember login dialog? ===== | ||
- | 這個問題除了避免使用password欄位以外,目前我沒有萬全之策。以下是我針對不同瀏覽器所觀察到的情況,版本與autocomplete部分相同: | ||
- | * IE: 宣告autocomplete="off"後就解決了。 | ||
- | * Firefox: 以Ajax Request取代傳統form的submit。 | ||
- | * Chrome: 即使以Ajax Request取代傳統form的submit一樣會出現。目前發現只要在http、可信任的https,且在帳號密碼欄位消失時,才會跳出來;帳號密碼欄位消失指的像是關閉Dialog的動作。 | ||
- | 以我們的軟體而言,最大問題是在Firefox上。這邊提供個範例給大家參考,如何做form的ajax submit,首先是html部分: | ||
- | <code html> | ||
- | <form id="form" name="form"> | ||
- | <input id="user" name="user" type="text" /> | ||
- | <input id="passwd" name="passwd" type="password" /> | ||
- | <input id="btn" type="button" value="shit"/> | ||
- | </form> | ||
- | </code> | ||
- | javascript部分,以JQuery為範例,我使用FormData物件來將內容轉為multipart的格式送往server: | ||
- | <code javascript> | ||
- | $( document ).ready(function() { | ||
- | $('#btn').click(function(){ | ||
- | console.log('submit form'); | ||
- | $("#form").submit(); | ||
- | }); | ||
- | |||
- | $("#form").submit(function(e){ | ||
- | var form = $(this); | ||
- | var formData = new FormData(form[0]); | ||
- | $.ajax({ | ||
- | type: "POST", | ||
- | url: 'shit.php', | ||
- | processData: false, | ||
- | contentType: false, | ||
- | data: formData, | ||
- | success: function(data) | ||
- | { | ||
- | console.log(data); // show response from the php script. | ||
- | } | ||
- | }); | ||
- | e.preventDefault(); | ||
- | }); | ||
- | |||
- | |||
- | }); | ||
- | </code> | ||
- | 以純javascript而言,使用以上方式就可以避免在firefox上跳出remember login dialog,但是在Apache Wicket 6上就沒這麼樂觀。下圖是我們在使用Wicket Form物件,並將multiple設為true後,發ajax request後的結果:\\ | ||
- | {{:java:web:wicket:wicket_submit_multiple_form.png|}}\\ | ||
- | 可以發現它並不是一個ajax request;追根究底到wicket-ajax-jquery.js中的submitMultipartForm,可以發現Wicket是使用iframe來模擬如ajax的request。從Wicket的[[https://github.com/apache/wicket/pull/255|Pull Request]]中可以得知,Wicket為了要相容於IE7~IE9,在舊版本的Wicket並沒使用FormData。如果要解決這個問題,有兩個方式: | ||
- | * 更新到Wicket8,它在[WICKET-6517]中使用真的Ajax取代了iframe。 | ||
- | * override submitMultipartForm。 | ||
- | 第二個方法大概這樣做: | ||
- | <code javascript> | ||
- | Wicket.Ajax.Call.prototype.submitMultipartForm = function(aContext){ | ||
- | var attrs = aContext.attrs; | ||
- | // ... do ajax request | ||
- | }; | ||
- | </code> | ||
- | 內容實做,可以參考[[https://github.com/apache/wicket/blob/master/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js|wicket-ajax-jquery.js]]內的doAjax,資料從aContext都可以拿到。\\ | ||
- | \\ | ||
- | 如果真的要完全解決這問題,請別使用password。 | ||
- | ===== Reference ===== | ||
- | * [[https://jsfiddle.net/449Lamue/6/|demo - 使用text模擬password]] | ||
- | * [[https://github.com/noppa/text-security|github - 使用text模擬password]] | ||
- | * [[https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion|How to Turn Off Form Autocompletion?]] | ||
- | * [[https://gist.github.com/runspired/b9fdf1fa74fc9fb4554418dea35718fe|Apply hidden fields]] | ||
- | * [[https://stackoverflow.com/questions/17719174/autocomplete-off-is-not-working-when-the-input-type-is-password-and-make-the|autocomplete ='off' is not working when the input type is password and make the input field above it to enable autocomplete]] | ||
- | * [[https://www.jianshu.com/p/46e6e03a0d53|通过jQuery Ajax使用FormData对象上传文件]] | ||
- | * [[https://github.com/apache/wicket/pull/255|Allow multipart submission of non modified FormData with Wicket.Ajax]] | ||
- | * [[https://wicket.apache.org/news/2018/02/17/wicket-8.0.0-M9-released.html|Apache Wicket 8.0.0-M9 released]] | ||
- | * [[https://github.com/apache/wicket/blob/master/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js|github - wicket-ajax-jquery.js]] | ||
- | |||
- | ====== ====== | ||
- | ---- | ||
- | \\ | ||
- | ~~DISQUS~~ |