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; }
需求git
關於驗證碼和惡意程序github
自動測試原理:函數
惡意程序:測試
驗證碼:ui
注意的問題this
解決方案spa
關於隨機數code
/* 時間戳做爲隨機種子 */ 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)); } }
驗證碼繪製:
圖片
- 登錄對話框須要驗證碼驗證機制避免惡意程序的破壞
- 驗證碼的產生須要隨機數的支持(時間戳爲隨機種子)
- 驗證碼必須附帶有效噪點
- 使用文本繪製的方式顯示驗證碼,而且驗證碼的字符須要單度繪製
倉庫ip
以上內容參考狄泰軟件學院系列課程,請你們保護原創!