跟帳號有關的系統,不管是網頁、手機App、或是單機桌面應用程式都可能遇上密碼,有些簡單點的會限制使用者的密碼文字長度要多長,複雜一點的還會限制密碼至少要包含某些內容,已達到足夠的複雜強度。本文提供Java、JavaScript與TypeScript的範例,提供檢測密碼是否符合強度的程式碼。
本頁文章顯示的程式碼範例,可隨意複製、修改、合併使用在任何程式碼中,不強制要求保留著作權聲明,且原作者不提供任何責任擔保。
強度說明
先決條件,達到密碼文字達到指定長度,沒有達成此條件直接返回不符合。再來檢查密碼內的文字是否包含以下四個項目,至少達成N個:
- 包含英文小寫
- 包含英文大寫
- 包含阿拉伯數字
- 包含特殊字元
同時提供前端與後端的檢查是為了增加使用者體驗,前端的使用者輸入密碼後即可透過JavaScript立刻檢查密碼強度,如果不符合就可以及時告知使用者需要加強密碼,不必等使用者Submit資料後才被告知有問題。而後端的密碼強度檢查(Java或NodeJS等)才是真正進行驗證的地方,前端可以不檢查,但至少後端要檢查。
程式範例說明
Java版
這邊做得比較簡單,只用String.matches
方法,Java內還有一個Pattern.compile
方法可以產生預先優化過的正規表達物件。另外Java中的matches方法必須要完全符合才會返回true
,因此只需要檢測是否包含的情況要在正規表達的前後加上.*
。
public class PasswordTool {
/**
* 檢查輸入的密碼強度,先檢查密碼是否達到指定的長度,
* 再檢查是否有達成包含「英文小寫、英文大寫、阿拉伯數字、特殊符號」四個項目,可透過`strength`設定至少要符合多少項。
* https://klab.tw/2023/01/check-password-strength-using-java-and-javascript/
* @param str - 要檢測的密碼文字
* @param length - 需要的密碼長度
* @param strength - 需要符合的項目數量,0到4
* @return 如果符合強度需求返回true
*/
public static boolean strengthChecke(String str, int length, int strength) {
if(str == null || str.length() < length) {
return false;
}
int n = 0;
var regex = new String[] {
".*[a-z].*",
".*[A-Z].*",
".*[0-9].*",
".*[`~!@#$%^&*()_+=,<>\\-\\[\\]\\{\\}\\:;\\.'\"\\/\\\\?\\|].*"
};
for(var r : regex) {
if(str.matches(r)) {
n++;
}
}
return n >= strength;
}
}
例如需要密碼長度至少八個字,密碼至少包含三種類型的文字(四取三)可以這樣輸入:
PasswordTool.strengthChecke(pwd, 8, 3);
JavaScript版
順便附上有JSDoc的說明,在Visual Studio Code等IDE中可以幫忙檢測JavaScript程式碼是否正確。
/**
* 檢查輸入的密碼強度,先檢查密碼是否達到指定的長度,
* 再檢查是否有達成包含「英文小寫、英文大寫、阿拉伯數字、特殊符號」四個項目,可透過`strength`設定至少要符合多少項。
* https://klab.tw/2023/01/check-password-strength-using-java-and-javascript/
* @param {string} str - 要檢測的密碼文字
* @param {number} length - 需要的密碼長度
* @param {number} strength - 需要符合的項目數量,0到4
* @returns 如果符合強度需求返回true
*/
function pwdStrengthChecke(str, length, strength) {
if(!str || str.length < length) {
return false
}
let n = 0
const regex = [
/[a-z]/,
/[A-Z]/,
/[0-9]/,
/[`~!@#$%^&*()_+=,<>\-\[\]\{\}\:;\.'"\/\\?\|]/
]
for(const r of regex) {
if(str.match(r)) {
n++
}
}
return n >= strength
}
JavaScript舊版(ES5)
前一個版本使用比較近代一點的JavaScript語法,這邊提供一個可用於舊版瀏覽器JavaScript的寫法。
/**
* 檢查輸入的密碼強度,先檢查密碼是否達到指定的長度,
* 再檢查是否有達成包含「英文小寫、英文大寫、阿拉伯數字、特殊符號」四個項目,可透過`strength`設定至少要符合多少項。
* https://klab.tw/2023/01/check-password-strength-using-java-and-javascript/
* @param {string} str - 要檢測的密碼文字
* @param {number} length - 需要的密碼長度
* @param {number} strength - 需要符合的項目數量,0到4
* @returns 如果符合強度需求返回true
*/
function pwdStrengthChecke(str, length, strength) {
if(!str || str.length < length) {
return false
}
var n = 0
var regex = [
/[a-z]/,
/[A-Z]/,
/[0-9]/,
/[`~!@#$%^&*()_+=,<>\-\[\]\{\}\:;\.'"\/\\?\|]/
]
for(var i = 0; i < regex.length ; i++) {
if(str.match(regex[i])) {
n++
}
}
return n >= strength
}
TypeScript版
目前開發上我很喜歡React搭配TypeScript,多了型別檢查可以減少很多奇妙的問題。
/**
* 檢查輸入的密碼強度,先檢查密碼是否達到指定的長度,
* 再檢查是否有達成包含「英文小寫、英文大寫、阿拉伯數字、特殊符號」四個項目,可透過`strength`設定至少要符合多少項。
* https://klab.tw/2023/01/check-password-strength-using-java-and-javascript/
* @param str - 要檢測的密碼文字
* @param length - 需要的密碼長度
* @param strength - 需要符合的項目數量,0到4
* @returns 如果符合強度需求返回true
*/
function pwdStrengthChecke(str: string, length: number, strength: number): boolean {
if(!str || str.length < length) {
return false
}
let n = 0
const regex = [
/[a-z]/,
/[A-Z]/,
/[0-9]/,
/[`~!@#$%^&*()_+=,<>\-\[\]\{\}\:;\.'"\/\\?\|]/
]
for(const r of regex) {
if(str.match(r)) {
n++
}
}
return n >= strength
}