驗證欄位與密碼加密

以下會用截圖搭配文字簡單描述每個功能的實作

欄位驗證

欄位的輸入驗證是用JQuery Validation Plugin
在HTML方面則是用一個Form包住所有的輸入欄位
在validate部分有四個區塊rule/errorPlacement/success/submitHandler

  • rule方面會對應input欄位的name屬性,至於裡頭的規則可以參考官網(支援正則)

  • errorPlacement則是發生錯誤時觸發,可以透過回傳的error和element動作,裡頭寫的errorInputShow就是讓欄位下方出現紅字。

  • success顧名思義就是欄位通過驗證時

  • submitHandler設置後可以等全部欄位通過驗成才submit

$("#signinForm").validate({
    rules:{
        loginAccount: {
            required: true,
            email: true
        },
        loginPwd: {
            required: true,
            rangelength: [6,20],
        }
    },
    errorPlacement: function(error, element){
        if(element.is("#loginAccount")){
            errorInputShow($("#loginAccount"),error[0].innerText);
        }else if(element.is("#loginPwd")){
            errorInputShow($("#loginPwd"), error[0].innerText);
        }
    },
    success: function(label) {
        if(label[0].htmlFor === "loginAccount"){
            successInputShow($("#loginAccount"));
        }else if(label[0].htmlFor === "loginPwd"){
            successInputShow($("#loginPwd"));
        }
    },
    submitHandler: function(){
        $this = $("#signinForm");
        var loginAccount = $this.find("input#loginAccount").val();
        var loginPwd = encrypt($this.find("input#loginPwd").val());
        var sendData = {"loginAccount":loginAccount ,"loginPwd":loginPwd};
        console.log(sendData);
        event.preventDefault();
        $.ajax({
            type: "POST",
            url: "http://127.0.0.1:3000/signin",
            data: sendData,
            success: function(data){
                console.log(data);
                window.location.replace("http://127.0.0.1:3000/users/" + loginAccount);
            },
            error: function(data){
                if(data.responseJSON == "AccountNotFound"){
                    errorInputShow($("#loginAccount"), "Account Not exists!");
                }else if(data.responseJSON == "WrongPwd"){
                    errorInputShow($("#loginPwd"), "Wrong PassWord");
                }else if(data.responseJSON == "Unval"){
                    $('#valModal').find("input#valAccount").val(loginAccount);
                    $('#valModal').modal('show');
                }
            }
        });
    }
});

這裡我有遇到一個坑是 原本打算錯誤訊息透過tooltip方式呈現
但是在帳號欄位有用Ajax驗證,Ajax返回後會影響原本欄位綁定的Event 所以成功返回後欄位不再有驗證功能,Tooltip也失效,我重新綁定後也沒有作用(不解啊!)所以就改回用append錯誤訊息方式表達。

密碼加密

密碼加密主要是在Client端加密,以免傳送明文被獲取
這邊我用的加密Library是Google提供的crypto-js
裡頭有提供對稱加密與非對稱加密,我是用hmac
我比較懶所以用固定的秘鑰,理論上在隨機產生秘鑰再一同存入會更難破解
在stackoverflow 有類似的討論:如何在client端加密

function encrypt(pwd){
    return CryptoJS.HmacMD5(pwd,"789123").toString();
}

有趣的是 有加密(更準確地說是映射Hash)不代表網站變得更安全,加密傳輸主要是不希望駭客輕鬆得到用戶密碼,用此去撞庫(用戶習慣每個網站都用一樣的帳密...)
駭客得到加密後的密碼一樣可以登入並取得使用者權限,所以更安全的做法應該是要讓Server定時更新秘鑰讓使用者多重加密(hash+salt),不斷改變密碼增加被破解與盜入的危機或是乾脆點用HTTPS(缺:自己練習要去申請憑證也不太可能啊,自建憑證也不會被瀏覽器信任OTZ)
資安這塊真是讓人敬仰的領域OTZ