界面展示

图片描述

核心概念

用户名和密码的获取

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));
    }
}

验证码绘制:
clipboard.png

总结

  • 登陆对话框需要验证码验证机制避免恶意程序的破坏
  • 验证码的产生需要随机数的支持(时间戳为随机种子)
  • 验证码必须附带有效噪点
  • 使用文本绘制的方式显示验证码,并且验证码的字符需要单度绘制

仓库

以上内容参考狄泰软件学院系列课程,请大家保护原创!


TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧