登入注册逻辑服务端(nginx+fastcgi+http+c++)

注册功能

#include"fcgio.h"
#include"fcgi_config.h"
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <sys/time.h>
#include <memory>

//#include "FastCGIApplication.h"
//#include "FastCGIErrorCode.h"

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/error/en.h"

#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
enum ResponseCode
{
    Succ = 0,
    Error = 1,

    //Error with user info
    UserError=10,
    UserExists=11,
    UserNotLogin,
    UserInvalid,

    //Error with file
    FileError=20,
    FileExists,
    FileNotExists
};

using namespace std;

using namespace rapidjson;

#define LOG_MODULE       "cgi"
#define LOG_PROC         "register"
class ConfigHelper
{
public:
    static ConfigHelper &getInstance(){return smInstance;}
    std::string getVal(std::string field,std::string key)
    {
        return this->mCfgRootMap[field][key];
    }

private:
    ConfigHelper()
    {
        /*ifstream ifs;
                        ifs.open("./conf/cfg.json");
                        if(!ifs.is_open())
                        {
                                throw runtime_error("Can not open file ./conf/cfg.json");
                        }
                        string content;
                        for(int read_sum = 0 ; !ifs.eof();)
                        {
                                char buf[1024];
                                ifs.read(buf,sizeof(buf)-1);
                                read_sum+=ifs.gcount();
                                buf[ifs.gcount()]='\0';
                                content+=buf;
                        }
                        Document d;
                        d.Parse(content.c_str());
                        map<string, map<string,string>> cfgRootMap;
                        auto root = d.GetObject();
                        for(auto it = root.begin(); it != root.end();++it)
                        {
                                map<string,string> childMap;
                                auto obj = it->value.GetObject();
                                for (auto itChild = obj.begin() ; itChild!=obj.end();++itChild)
                                {
                                        childMap.insert(make_pair(itChild->name.GetString(),itChild->value.GetString()));
                                }
                                cfgRootMap.insert(make_pair(it->name.GetString(),childMap));
                        }
                        this->mCfgRootMap.swap(cfgRootMap);*/
    }

    ConfigHelper(const ConfigHelper&);
    static ConfigHelper smInstance;
    std::map<std::string,std::map<std::string,std::string>> mCfgRootMap;
};

ConfigHelper ConfigHelper::smInstance;


class FastCGIApplication
{
public:
    FastCGIApplication()
    {
    }
    virtual ~FastCGIApplication()
    {

    }

    //当请求是Get方法的时候,run会调用这个函数
    //headers:是FastCGI的各个环境变量的key val值
    virtual void Get(map<string,string> headers)
    {
        //默认情况下没有实现该方法统一
        //返回405错误,不支持该方法
        cout<<"Status: 405 Method Not Allowed\r\n";
    }

    //当请求是Post方法的时候,run会调用这个函数
    //headers:是FastCGI的各个环境变量的key val值
    //data:是请求数据的内容
    //len:请求数据的长度
    virtual void Post(map<string,string> headers,char *data,size_t len)
    {
        //默认情况下没有实现该方法统一
        //返回405错误,不支持该方法
        cout<<"Status: 405 Method Not Allowed\r\n";
    }

    //FastCGI主要运行函数,类似于Qt的Application::run
    virtual int run()
    {
        std::cout<<"this  fastcgi program staring"<<std::endl;
        streambuf * cin_streambuf  = cin.rdbuf();
        streambuf * cout_streambuf = cout.rdbuf();
        streambuf * cerr_streambuf = cerr.rdbuf();

        FCGX_Request request;

        FCGX_Init();
        FCGX_InitRequest(&request, 0, 0);

        //阻塞等待用户连接
        while (FCGX_Accept_r(&request) == 0)
        {
            fcgi_streambuf cin_fcgi_streambuf(request.in);
            fcgi_streambuf cout_fcgi_streambuf(request.out);
            fcgi_streambuf cerr_fcgi_streambuf(request.err);

#if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
            cin  = &cin_fcgi_streambuf;
            cout = &cout_fcgi_streambuf;
            cerr = &cerr_fcgi_streambuf;
#else
            cin.rdbuf(&cin_fcgi_streambuf);
            cout.rdbuf(&cout_fcgi_streambuf);
            cerr.rdbuf(&cerr_fcgi_streambuf);
#endif

            //分离env的key和value转化
            map<string,string> headers;
            for(auto envStr = request.envp ; *envStr!=nullptr;++envStr)
            {
                string s = *envStr;
                auto pos = s.find('=');
                string key = s.substr(0,pos);
                string value = s.substr(pos+1);
                headers.insert(make_pair(key,value));
            }

            //抽取content_length来操作请求数据
            auto itContentLength = headers.find("CONTENT_LENGTH");
            size_t contentLength = 0;
            if(itContentLength!=headers.end())
            {
                auto strContentLenght = itContentLength->second;
                contentLength = strContentLenght.empty()?0:stoll(strContentLenght);
            }
            //使用智能指针管理内存,自动释放
            unique_ptr<char[]> uptr;
            if(contentLength!=0)
            {
                //有请求数据,将其全部读出放到一块内存
                char *data=new char[contentLength];
                uptr.reset(data);
                size_t read_sum=0;
                for(;!cin.eof()&&read_sum<contentLength;)
                {
                    char buf[1024];
                    size_t readLen=0;
                    memset(buf,0,sizeof(buf));
                    cin.read(buf,sizeof(buf));
                    readLen = cin.gcount();
                    memcpy(data+read_sum,buf,readLen);
                    read_sum+=readLen;
                }
                //加保护,特殊情况,如果传输过来的content lenght 和最终读取字节数不符,要防止
                if(read_sum!=contentLength)
                {
                    continue;
                }
            }
            //使用智能指针自动释放
            auto requestMethod = headers["REQUEST_METHOD"];
            if(requestMethod=="GET")
            {
                this->Get(headers);
            }
            else if(requestMethod=="POST")
            {
                this->Post(headers,uptr.get(),contentLength);
            }
            else
            {
                //不支持的方法返回405错误
                cout<<"Status: 405 Method Not Allowed\r\n";
            }
        }
#if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
        cin  = cin_streambuf;
        cout = cout_streambuf;
        cerr = cerr_streambuf;
#else
        cin.rdbuf(cin_streambuf);
        cout.rdbuf(cout_streambuf);
        cerr.rdbuf(cerr_streambuf);
#endif

        return 0;

    }
};


class RegisterCGIApplication:public FastCGIApplication
{
public:
    struct RegisterInfo
    {
        string userName;
        string nickName;
        string phone;
        string passwd;
        string email;
    };

    RegisterInfo getRegisterInfo(string json)
    {
        Document d;
        if(d.Parse(json.c_str()).HasParseError())
        {
            throw runtime_error(
                        string("parse json "+ json +" error :") +
                        GetParseError_En(d.GetParseError()));
        }
        return {
            d["userName"].GetString(),
                    d["nickName"].GetString(),
                    d["phone"].GetString(),
                    d["passwd"].GetString(),
                    d["email"].GetString()
        };
    }
    void Post(map<string,string>,char *data,size_t len)
    {
        int resultCode=Succ;
        unique_ptr<sql::Connection> con(nullptr);
        try{
            do
            {
                //1 解析json
                string content(data,data+len);
                auto regInfo = this->getRegisterInfo(content);

                //2 mysql查询
                sql::Driver *driver;
                driver = ::get_driver_instance();
                string mysqlHost = "159.75.127.51";//ConfigHelper::getInstance().getVal("mysql","ip");
                string mysqlPort="3306";// ConfigHelper::getInstance().getVal("mysql","port");
                string mysqlDBName= "edison";//ConfigHelper::getInstance().getVal("mysql","database");
                string mysqlUser="root";// ConfigHelper::getInstance().getVal("mysql","user");
                string mysqlPasswd= "lwx856839";//ConfigHelper::getInstance().getVal("mysql","password");
                con.reset(driver->connect("tcp://"+mysqlHost+":"+mysqlPort,mysqlUser,mysqlPasswd));
                con->setSchema(mysqlDBName);
                //关闭自动提交--开启事务
                con->setAutoCommit(false);

                unique_ptr<sql::PreparedStatement> prepStat(con->prepareStatement("select * from userinfo where name = ?"));
                prepStat->setString(1,regInfo.userName);
                unique_ptr<sql::ResultSet> res(prepStat->executeQuery());
                if(res->next())
                {
		   std::cout<<"have data coming"<<std::endl;
                    resultCode=UserExists;
                    break;
                }
                //3 mysql插入一条数据到用户表
                prepStat.reset(con->prepareStatement("insert into userinfo(name,nickname,password,phone,createtime,email) values(?,?,?,?,now(),?)"));
                prepStat->setString(1,regInfo.userName);
                prepStat->setString(2,regInfo.nickName);
                prepStat->setString(3,regInfo.passwd);
                prepStat->setString(4,regInfo.phone);
                prepStat->setString(5,regInfo.email);
                if(prepStat->executeUpdate()!=1)
                {
                    resultCode=Error;
                    break;
                }
                con->commit();
            }while(0);
        }
        catch(const exception &e)
        {
            //LOG(LOG_MODULE,LOG_PROC,"exception:%s\n",e.what());
            resultCode=Error;
            if(con.get()!=nullptr)
            {
                con->rollback();
            }
        }

        //构建返回结果
        StringBuffer sb;
        Writer<StringBuffer> writer(sb);
        writer.StartObject();               // Between StartObject()/EndObject(),
        writer.Key("code");
        writer.Int(resultCode);
        writer.EndObject();
        cout << "Content-type: application/json\r\n\r\n";
        cout<<sb.GetString();
    }
};

int main()
{
	RegisterCGIApplication app;
	return app.run();
}

登入功能

#include <map>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include<iostream>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/error/en.h"

#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "fcgio.h"
#include "fcgi_config.h"  // HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
#include <memory>
#include <string>
#include <map>
#include <cstring>

using namespace std;
using namespace rapidjson;

#define LOG_MODULE       "cgi"
#define LOG_PROC         "login"
enum ResponseCode
{
    Succ = 0,
    Error = 1,

    //Error with user info
    UserError=10,
    UserExists=11,
    UserNotLogin,
    UserInvalid,

    //Error with file
    FileError=20,
    FileExists,
    FileNotExists
};
typedef struct LoginInfo
{
   string userName;
   string passwd;
   string nickName;
   string phone;
   string email;
   long long id;
}LoginInfo;
//作为所有FastCGI的基类使用
class FastCGIApplication
{
public:
    FastCGIApplication()
    {

    }
    virtual ~FastCGIApplication()
    {

    }

    //当请求是Get方法的时候,run会调用这个函数
    //headers:是FastCGI的各个环境变量的key val值
    virtual void Get(map<string,string> headers)
    {
        //默认情况下没有实现该方法统一
        //返回405错误,不支持该方法
        cout<<"Status: 405 Method Not Allowed\r\n";
    }

    //当请求是Post方法的时候,run会调用这个函数
    //headers:是FastCGI的各个环境变量的key val值
    //data:是请求数据的内容
    //len:请求数据的长度
    virtual void Post(map<string,string> headers,char *data,size_t len)
    {
        //默认情况下没有实现该方法统一
        //返回405错误,不支持该方法
        cout<<"Status: 405 Method Not Allowed\r\n";
    }

    //FastCGI主要运行函数,类似于Qt的Application::run
    virtual int run()
    {
        streambuf * cin_streambuf  = cin.rdbuf();
        streambuf * cout_streambuf = cout.rdbuf();
        streambuf * cerr_streambuf = cerr.rdbuf();

        FCGX_Request request;

        FCGX_Init();
        FCGX_InitRequest(&request, 0, 0);

        //阻塞等待用户连接
        while (FCGX_Accept_r(&request) == 0)
        {
            fcgi_streambuf cin_fcgi_streambuf(request.in);
            fcgi_streambuf cout_fcgi_streambuf(request.out);
            fcgi_streambuf cerr_fcgi_streambuf(request.err);

#if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
            cin  = &cin_fcgi_streambuf;
            cout = &cout_fcgi_streambuf;
            cerr = &cerr_fcgi_streambuf;
#else
            cin.rdbuf(&cin_fcgi_streambuf);
            cout.rdbuf(&cout_fcgi_streambuf);
            cerr.rdbuf(&cerr_fcgi_streambuf);
#endif

            //分离env的key和value转化
            map<string,string> headers;
            for(auto envStr = request.envp ; *envStr!=nullptr;++envStr)
            {
                string s = *envStr;
                auto pos = s.find('=');
                string key = s.substr(0,pos);
                string value = s.substr(pos+1);
                headers.insert(make_pair(key,value));
            }

            //抽取content_length来操作请求数据
            auto itContentLength = headers.find("CONTENT_LENGTH");
            size_t contentLength = 0;
            if(itContentLength!=headers.end())
            {
                auto strContentLenght = itContentLength->second;
                contentLength = strContentLenght.empty()?0:stoll(strContentLenght);
            }
            //使用智能指针管理内存,自动释放
            unique_ptr<char[]> uptr;
            if(contentLength!=0)
            {
                //有请求数据,将其全部读出放到一块内存
                char *data=new char[contentLength];
                uptr.reset(data);
                size_t read_sum=0;
                for(;!cin.eof()&&read_sum<contentLength;)
                {
                    char buf[1024];
                    size_t readLen=0;
                    memset(buf,0,sizeof(buf));
                    cin.read(buf,sizeof(buf));
                    readLen = cin.gcount();
                    memcpy(data+read_sum,buf,readLen);
                    read_sum+=readLen;
                }
                //加保护,特殊情况,如果传输过来的content lenght 和最终读取字节数不符,要防止
                if(read_sum!=contentLength)
                {
                    continue;
                }
            }
            //使用智能指针自动释放
            auto requestMethod = headers["REQUEST_METHOD"];
            if(requestMethod=="GET")
            {
                this->Get(headers);
            }
            else if(requestMethod=="POST")
            {
                this->Post(headers,uptr.get(),contentLength);
            }
            else
            {
                //不支持的方法返回405错误
                cout<<"Status: 405 Method Not Allowed\r\n";
            }
        }
#if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
        cin  = cin_streambuf;
        cout = cout_streambuf;
        cerr = cerr_streambuf;
#else
        cin.rdbuf(cin_streambuf);
        cout.rdbuf(cout_streambuf);
        cerr.rdbuf(cerr_streambuf);
#endif

        return 0;
    }
};




class LoginCGIApplication:public FastCGIApplication
{
public:

    LoginCGIApplication()
    {
    }

    LoginInfo ParseRequestJson(const string json)
    {
        Document d;
        if(d.Parse(json.c_str()).HasParseError())
        {
            throw runtime_error(
                    string("parse json "+ json +" error :") +
                    GetParseError_En(d.GetParseError()));
        }
        return {
            d["userName"].GetString(),
            d["passwd"].GetString()
        };
    }

    bool ValidateUser(LoginInfo &info)
    {
        unique_ptr<sql::Connection> con(nullptr);
        bool result = false;
        try
        {
            sql::Driver *driver;
            driver = ::get_driver_instance();
            string mysqlHost ="159.75.127.51";//ConfigHelper::getInstance().getVal("mysql","ip");
            string mysqlPort="3306"; //ConfigHelper::getInstance().getVal("mysql","port");
            string mysqlDBName="edison"; //ConfigHelper::getInstance().getVal("mysql","database");
            string mysqlUser="root"; //ConfigHelper::getInstance().getVal("mysql","user");
            string mysqlPasswd="lwx856839"; //ConfigHelper::getInstance().getVal("mysql","password");
            con.reset(driver->connect("tcp://"+mysqlHost+":"+mysqlPort,mysqlUser,mysqlPasswd));

            con->setSchema(mysqlDBName);
            unique_ptr<sql::PreparedStatement> prepStat(con->prepareStatement("select id,nickname,phone,email from userinfo where name = ? and password = ?"));
            prepStat->setString(1,info.userName);
            prepStat->setString(2,info.passwd);
            unique_ptr<sql::ResultSet> res(prepStat->executeQuery());
            if(res->next())
            {
                info.id=res->getUInt("id");
                info.phone = res->getString("phone");
                info.nickName = res->getString("nickname");
                info.email = res->getString("email");
                result = true;
            }
        }
        catch(const sql::SQLException &e)
        {
           // LOG(LOG_MODULE,LOG_PROC,"sql exception:%s\n",e.what());
        }
        catch(const exception &e)
        {
            //LOG(LOG_MODULE,LOG_PROC,"exception:%s\n",e.what());
        }
        catch(...)
        {
            //LOG(LOG_MODULE,LOG_PROC,"unknown exception:%s\n");
        }
        return result;
    }

    void Post(map<string,string>,char *data ,size_t len)
    {
        int resultCode = Succ;
        string token;
        try
        {
            do
            {
                //1 解析输入数据
                string content(data,data+len);
                // LOG(LOG_MODULE,LOG_PROC,"data:%s\n",content.c_str());
                auto info = this->ParseRequestJson(content);
                //2 验证用户信息
                if(!this->ValidateUser(info))
                {
                    resultCode = UserInvalid;
                    break;
                }
                // LOG(LOG_MODULE,LOG_PROC,"userName:%s passwd:%s , phone :%s id:%d email:%s\n",info.userName.c_str(),info.passwd.c_str(),info.phone.c_str(),info.id,info.email.c_str());
                //3 产生token ,不过已经合并到以下方法,存入信息到redis同时返回token
                //4 将token写入到redis
                // LOG(LOG_MODULE,LOG_PROC,"token:%s\n",token.c_str());
               // token = TokenHelper::WriteInfoToRedis(info);
            }while(0);
        }
        catch(const exception &e)
        {
            //LOG(LOG_MODULE,LOG_PROC,"exception:%s\n",e.what());
            resultCode=Error;
        }
        //5 返回结果给客户端
        //构建返回结果
        StringBuffer sb;
        Writer<StringBuffer> writer(sb);
        writer.StartObject();
        writer.Key("code");
        writer.Int(resultCode);
        writer.Key("token");
        writer.String(token.c_str(),static_cast<rapidjson::SizeType>(token.length()));
        writer.EndObject();
        cout << "Content-type: application/json\r\n\r\n";
        cout<<sb.GetString()<<endl;
    }
};

int main()
{
    LoginCGIApplication app;
    return app.run();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值