2_登陸對話方塊的設計 - 可複用
介面展示
核心概念
使用者名稱和密碼的獲取
void QLoginDialog::onLoginBtnClicked() { if( m_captcha.toLower() == m_captchaEdit.text().toLower() ) { m_user = m_userEdit.text().trimmed(); m_password = m_passwordEdit.text(); if( m_user != "" && m_password != "") { done(QDialog::Accepted); } else { QMessageBox(QMessageBox::Critical, "錯誤", "使用者名稱或密碼輸入有誤", QMessageBox::Ok, this, Qt::Drawer).exec(); } } else { QMessageBox(QMessageBox::Critical, "錯誤", "驗證碼輸入有誤", QMessageBox::Ok, this, Qt::Drawer).exec(); qsrand(static_cast<uint>((QTime::currentTime().second() * 1000 + QTime::currentTime().msec()))); m_captcha = getCaptcha(); } }
QString QLoginDialog::getUser() { return m_user; } QString QLoginDialog::getPassword() { return m_password; }
隨機驗證碼生成
-
需求
- 隨機產生驗證碼
- 使用者識別後填寫
- 判斷使用者識別的正確性
- 可以有效避開惡意程式的識別
-
關於驗證碼和惡意程式
-
自動測試原理:
- 利用一些特殊的系統函式能夠通過程式碼控制程式,從而模擬使用者操作
-
惡意程式:
- 使用自動測試原理對目標程式進行控制,從而盜取資訊或進行攻擊
-
驗證碼:
- 隨機產生,使用者容易識別,程式難以識別,從而有效避免惡意攻擊
-
-
注意的問題
- 驗證碼必須動態隨機產生
- 驗證碼的顯示避開使用標準組件(標籤,文字框等)
- 驗證碼應該附帶足夠多的障礙增加程式識別難度
-
解決方案
- 隨機產生目標驗證碼
- 將隨機驗證碼直接繪製於登陸對話方塊(驗證碼中的每一個字元必須分開繪製)
- 驗證碼中的字元顏色隨機改變
- 在驗證碼區域隨機繪製噪點
-
關於隨機數
- 計算機無法產生真正意義上的隨機數
- 計算機只能模擬隨機序列(偽隨機數)
- 隨機種子決定每次產生的隨機序列是否相同( 一般以時間戳作為隨機種子 )
/* 時間戳作為隨機種子 */ qsrand(static_cast<uint>((QTime::currentTime().second() * 1000 + QTime::currentTime().msec())));
/** * @brief 獲取隨機驗證碼 */ QString QLoginDialog::getCaptcha() { QString ret = ""; for(int i=0; i<4; i++) { int c = (qrand() % 2) ? 'a' : 'A'; ret += static_cast<QChar>(c + qrand() % 26); } return ret; } /** * @brief 獲取隨機顏色值 */ Qt::GlobalColor* QLoginDialog::getColor() { static Qt::GlobalColor color[4]; for(int i=0; i<4; i++) { color[i] = static_cast<Qt::GlobalColor>((2 + qrand() % 16)); } return color; } /** * @brief 定週期獲取隨機顏色值 * @brief 強制進行介面繪製 */ void QLoginDialog::Timer_TimeOut() { m_colors = getColor(); update(); }
void QLoginDialog::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setFont(QFont("consolas", 12)); painter.fillRect(151, 67, 70, 20, Qt::white); for(int i=0; i<150; i++)// 噪點繪製 { painter.setPen(m_colors[i % 4]); painter.drawPoint(151 + qrand() % 70, 67 + qrand() % 20); } for(int i=0; i<4; i++)// 驗證碼字元分開繪製 { painter.setPen(m_colors[i]); painter.drawText(151 + i*17, 67, 17, 20, Qt::AlignCenter, m_captcha.at(i)); } }
驗證碼繪製:
總結
登陸對話方塊需要驗證碼驗證機制避免惡意程式的破壞
驗證碼的產生需要隨機數的支援(時間戳為隨機種子)
驗證碼必須附帶有效噪點
使用文字繪製的方式顯示驗證碼,並且驗證碼的字元需要單度繪製
以上內容參考狄泰軟體學院系列課程,請大家保護原創!