نگهداری پسورد در مرورگرها

مقدار پسورد وارد شده، به صورت متن ساده (Plain Text) و بدون رمزگذاری در 1 DOM ذخیره می‌گردد. در واقع مرورگر در زمان نمایش فقط ظاهر آن را تغییر می‌دهد (mask). مثلا همه کاراکترهای ورودی را تبدیل به می‌کند.

💡 در source صفحه، مقدار پسورد وجود نخواهد داشت.
بنابراین مقدار Value برابر با "" خواهد بود و یا اصلا value برای input وجود نخواهد داشت.


روش بدست آوردن

با JavaScript

در DevTools مرورگر و در زبانه console:
  1. با استفاده از متد getElementById و نام فیلد که در html به عنوان id استفاده می‌شود
document.getElementById('P9999_PASSWORD').value; 
  1. با استفاده از متد querySelector و نوع password
document.querySelector('input[type="password"]').value

getElementById / querySelector

با تبدیل نوع

در DevTools (کلید F12) مرورگر و در زبانه insepector:
می‌توانیم نوع input را از passwprd به text تغییر دهیم type = password type = text


پیاده سازی در Oracle APEX

روش اول

می‌خواهیم کاربر با کلیک کردن بر روی آیکون، پسورد را مشاهده کند/نکند.

  1. در صفحه Login بر روی آیتم Password کلیک می‌کنیم:
  • Identification
    • Name: P9999_PASSWORD
  • Advanced
    • Post Text:
<span
    style = "cursor: pointer;"
    class="fa fa-eye-slash"
    title = 'نمایش گذرواژه'
    onClick = "togglePass('P9999_PASSWORD', this)"
    >
    
</span>

در قسمت Post Text یک عنصر span به صفحه اضافه می‌کنیم تا آیکون چشم را بتوانیم نمایش دهیم و با کلیک کردن بر روی آن متد togglePass اجرا شود. این متد دارای دو پارامتر است:

  1. pass: نام فیلد پسورد
  2. icon: محلی که کلیک کرده‌ایم و می‌خواهیم کلاس آیکون آن را تغییر دهیم؛ بنابراین از کلمه کلیدی this استفاده می‌کنیم.
    • آیکون چشم: fa fa-eye
    • آیکون چشم خط خورده: fa fa-eye-slash

2. در قسمت خصوصیات Page متد JavaScript زیر را اضافه می‌کنیم:

با استفاده از این متد و با هر کلیک، آیکون‌ها را تعویض و نوع input را از password به text و برعکس تغییر می‌دهیم.


  • Page | JavaScript | Function and Global Variable Declaration
function togglePass(itemId, icon) {
    const pass = document.getElementById(itemId);

    if (pass.type === 'password') {
        pass.type = 'text';
        icon.className = 'fa fa-eye-slash';
        icon.title = 'پنهان کردن گذرواژه'
    }
    else {
        pass.type = 'password';
        icon.className = 'fa fa-eye';
        icon.title = 'نمایش گذرواژه'
    }
}

🔔 نمونه دیگر، استفاده از یک checkbox به جای آیکون:    Checkbox


روش دوم

در این روش می‌خواهیم ریسک دیده شدن پسورد را کاهش دهیم، بدین شکل که با از دست دادن focus در محدوده پسورد، پسورد مخفی شود.

برای span پسورد:

  1. برای ایجاد focus بر روی آن از tabindex=0 استفاده می‌کنیم. ( tabindex )

💡 اگر نخواهیم کاربر با کلید tab به این قسمت برسد و فقط focus را داشته باشیم، مقدار tabindex را «-1» می‌نویسیم.

tabindex = -1
  1. برای جلوگیری از اجرای متد پیش‌فرض، onclick آن را برابر با return false قرار می‌دهیم. در این مورد اگر ننویسیم هم اتفاقی نخواهد افتاد!
  • Pasword Item (P9999_PASSWORD) | Advanced | Post Text:
<span
    id="my-toggle-icon"
    tabindex="0"
    class="fa fa-eye-slash"
    title="نمایش گذرواژه"
    style="cursor:pointer"
    onclick="return false;">
    
</span>

در خصوصیات صفحه یک متد به نام initPasswordToggle ایجاد می‌کنیم که شامل موارد زیر باشد:

  1. در APEX فیلد پسورد و span (نمایش/عدم نمایش)، داخل یک div با کلاس t-Form-itemWrapper قرار می‌گیرند. می‌خواهیم با از دست دادن focus در هر یک از فرزندان این div، متد hide اجرا شود.
    • با استفاده از فیلد پسورد و متد closest به اولین والد آن که div مورد نظر ما هست ، خواهیم رسید.
    • نام آن را wrapper می‌گذاریم.

alt text

const pass = document.getElementById(passwordId);
const icon = document.getElementById(iconId);
const wrapper = pass.closest('.t-Form-itemWrapper');
  1. دو متد hide و show اضافه می‌کنیم.
  2. برای span، رویداد کلیک را تعریف می‌کنیم.
 function hide() {
        pass.type = 'password';
        icon.className = 'fa fa-eye-slash';
        icon.title = 'نمایش گذرواژه';
    }

    function show() {
        pass.type = 'text';
        icon.className = 'fa fa-eye';
        icon.title = 'پنهان کردن گذرواژه';
    }

    icon.addEventListener('click', function (e) {
        // e.preventDefault(); // جلوگیری از رفتار پیش‌فرض
        pass.type === 'password' ? show() : hide();
        icon.focus(); 
    });
  1. بر روی wrapper یک listener برای رویداد focusout ایجاد می‌کنیم تا خروج focus را بر روی تمام فرزندان آن مدیریت کنیم. تا زمانی که focus از wrapper خارج نشود، پسورد نمایش داده خواهد شد. در غیر این صورت متد hide اجرا خواهد شد.
    • e.relatedTarget عنصری است که قرار است focus به آن برود. مثلا کاربر بر روی فیلد نام کاربری کلیک می‌کند و مقدار relatedTarget برابر با این عنصر خواهد شد.
    • اگر این عنصر جزو فرزندان wrapper باشد (input یا span)، متد خاتمه می‌یابد، در غیر این صورت متد hide اجرا می‌شود.
 wrapper.addEventListener('focusout', function (e) {
        const focusTo = e.relatedTarget;
        
        if (focusTo && wrapper.contains(focusTo)) {
            return;
        }
        hide();
    });

کد نهایی

  • Page | JavaScript | Function and Global Variable Declaration
function initPasswordToggle(passwordId, iconId) {

    const pass = document.getElementById(passwordId);
    const icon = document.getElementById(iconId);
    const wrapper = pass.closest('.t-Form-itemWrapper');

    // if (!pass || !icon || !wrapper) return;

    function hide() {
        pass.type = 'password';
        icon.className = 'fa fa-eye-slash';
        icon.title = 'نمایش گذرواژه';
    }

    function show() {
        pass.type = 'text';
        icon.className = 'fa fa-eye';
        icon.title = 'پنهان کردن گذرواژه';
    }

    icon.addEventListener('click', function (e) {
        // e.preventDefault(); // جلوگیری از رفتار پیش‌فرض
        pass.type === 'password' ? show() : hide();
        icon.focus(); 
    });

    wrapper.addEventListener('focusout', function (e) {
        const focusTo = e.relatedTarget;
        
        if (focusTo && wrapper.contains(focusTo)) {
            return;
        }
        hide();
    });

}
// فراخوانی متد
initPasswordToggle('P9999_PASSWORD', 'my-toggle-icon');