一、前言
搭建HTTP服务器后,部署在公网服务器上时需要保证一定的安全性,这里将介绍最基本的登录验证后如何生成限时token来验证后续的请求消息。在Qt中可以使用#include 来生成通用唯一识别码,可以以此来生成token。如果需要提升安全性,可以使用QCryptographicHash::hash()来进行二次处理。
二、头文件定义说明
头文件代码如下,这里只使用QUuid生成唯一识别码来作为token,其中TOKEN_TIMEOUT_SECONDS定了token的生效时长,lastActiveTime定义了token的激活时间,后续以此来判断token是否失效。
C++
#ifndef TOKENMANAGER_H
#define TOKENMANAGER_H
#include <QObject>
#include <QMap>
#include <QDateTime>
#include <QUuid>
#include <QMutex>
#define TOKEN_TIMEOUT_SECONDS (12 * 60 * 60) // 12小时
struct TokenInfo
{
QString username;
QDateTime lastActiveTime;
};
class TokenManager
{
public:
static TokenManager& instance()
{
static TokenManager ins;
return ins;
}
QString createToken(const QString& username);
bool validateToken(const QString& token);
void removeExpiredTokens();
private:
TokenManager() {}
QMap<QString, TokenInfo> m_tokenMap;
QMutex m_mutex;
};
#endif
三、源文件的定义
代码如下,实现三个函数,createToken()创建token,validateToken()查看token是否正确,removeExpiredTokens()清理失效的token。
C++
#include "TokenManager.h"
QString TokenManager::createToken(const QString& username)
{
QString token = QUuid::createUuid().toString().remove("{").remove("}");
//如果需要提高安全性
// QByteArray raw = QUuid::createUuid().toByteArray();
// QString token = QCryptographicHash::hash(raw, QCryptographicHash::Sha256).toHex();
TokenInfo info;
info.username = username;
info.lastActiveTime = QDateTime::currentDateTime();
QMutexLocker locker(&m_mutex);
m_tokenMap[token] = info;
return token;
}
bool TokenManager::validateToken(const QString& token)
{
//暂时废弃token
// return true;
QMutexLocker locker(&m_mutex);
if (!m_tokenMap.contains(token))
return false;
TokenInfo &info = m_tokenMap[token];
if (info.lastActiveTime.secsTo(QDateTime::currentDateTime()) > TOKEN_TIMEOUT_SECONDS)
{
m_tokenMap.remove(token);
return false;
}
// 刷新活跃时间
info.lastActiveTime = QDateTime::currentDateTime();
return true;
}
void TokenManager::removeExpiredTokens()
{
QMutexLocker locker(&m_mutex);
QList<QString> keys = m_tokenMap.keys();
for (const QString& key : keys){
if (!validateToken(key)){
m_tokenMap.remove(key);
}
}
}
四、补充说明
从上面的源码中可以看到没有调用removeExpiredTokens()来清理token,这是因为这里是测试,如果正式使用时可以使用定时器定时清理失效的token,代码如下,推荐1小时一次:
C++
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, [](){
TokenManager::instance().removeExpiredTokens();
});
timer->start(3600000);