Kaynağa Gözat

增加https及多域名支持

xx 2 yıl önce
ebeveyn
işleme
da457c5e62

+ 3 - 0
CMakeLists.txt

@@ -59,6 +59,8 @@ set_target_properties(${FASTWEBCORE} PROPERTIES OUTPUT_NAME_DEBUG "${FASTWEBCORE
 
 
 
+
+
 link_directories(/usr/lib/x86_64-linux-gnu)
 link_directories(/usr/local/lib)
 
@@ -127,6 +129,7 @@ endif()
 
 add_executable(${PROJECT_NAME} tests/main.cpp)
 target_link_libraries(${PROJECT_NAME} ${FASTWEBCORE})
+set_target_properties(${PROJECT_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}")
 ########################  安装  ########################
 install(TARGETS ${FASTWEBCORE} DESTINATION $<IF:$<CONFIG:Debug>,bin/debug,bin/release>)
 install(TARGETS ${PROJECT_NAME} DESTINATION $<IF:$<CONFIG:Debug>,bin/debug,bin/release>)

+ 28 - 10
config.ini

@@ -1,5 +1,6 @@
 [variable]
 base=${current_dir}
+
 [scripts]
 ; 应用目录(可执行脚本)
 ; 考虑安全性,请勿放置于网站静态文件目录
@@ -9,7 +10,7 @@ lib_dir=${base}/scripts/lib
 ; LUA虚拟机缓存数量(并发越高越大)-建议:10
 lua_cache_size=3000
 ; 脚本映射网站目录
-; 例如 D:/root/scripts/app/regist.lua 是脚本路径,app_mapping_dir设置的是/scripts,浏览器访问地址:http://127.0.0.1/scripts/regist.lua
+; 例如 app_mapping_dir设置的是/api,app_dir目录下有regist.lua,则浏览器访问地址:http://127.0.0.1/scripts/regist.lua
 ; 注意:必须/结尾
 app_mapping_dir=/scripts/
 ; 自动检测文件修改时间(秒)
@@ -32,15 +33,32 @@ Initialization_script=${base}/scripts/init.lua
 interceptor_scripts= [["${base}/scripts/interceptor.lua","/scripts/*.*"]]
 ; 调试模式,开启后控制台输出异常错误信息 (0=关闭 1=开启)
 debug=1
-[server]
-; TCP服务监听地址
-address=0.0.0.0
-; TCP服务监听端口
-; 启用SSL:443
-; 不启用SSL:80或其它
-port=8888
-
-
+; 绑定域名
+domain=["local.newobj.org","127.0.0.1"]
 
+; 域名配置信息,具体根据 website->domain 而定
+[local.newobj.org]
+; 是否为HTTPS
+https=1
+;HTTPS证书,完全兼容Nginx证书
+; 证书KEY
+ssl_key=${base}/config/ssl/local.newobj.org.key
+; 证书PEM文件
+ssl_pem=${base}/config/ssl/local.newobj.org.pem
+; 证书CA文件(默认:空)
+ssl_ca=
+; 证书密码(默认:空)
+ssl_pwd=
+; ================验证类型=================
+; 0 = 完全忽略验证证书的结果。当握手必须完成的话,就选中这个选项。其实真正有证书的人很少,尤其是在中国,那么如果 SSL 运用于一些免费的服务,比如 EMAIL 的时候,SERVER 端最好采用这个模式。
+; 1 = 希望验证对方的证书。这个是最一般的模式。对 CLIENT 来说,如果设置了这样的模式,验证SERVER的证书出了任何错误,SSL 握手都告吹。对 SERVER 来说,如果设置了这样的模式,CLIENT 倒不一定要把自己的证书交出去。如果 CLIENT 没有交出证书,SERVER 自己决定下一步怎么做。
+; 2 = 这是 SERVER 使用的一种模式,在这种模式下, SERVER 会向 CLIENT 要证书。如果 CLIENT 不给,SSL 握手告吹
+; 3 = 这是仅能使用在 SSL SESSION RENEGOTIATION 阶段的一种方式。如果不是用这个模式的话,那么在 RENEGOTIATION 的时候,CLIENT 都要把自己的证书送给 SERVER,然后做一番分析。这个过程很消耗 CPU 时间的,而这个模式则不需要 CLIENT 在 RENEGOTIATION 的时候重复送自己的证书了。
+ssl_ver_type=0
+; 端口,默认https为443,http为80
+port=8566
 
+[127.0.0.1]
+https=0
+port=8866
 

+ 28 - 0
config/ssl/local.newobj.org.key

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBiTdJOfaHJ0L4
+BYyiN+CF5uL82wFjfrn5evWwKZ6Ie0JxDkzG/okswhtwvU75g5uhWbWzdQR47EmP
+uGJnrw1apVOnzV9e6XuTc2o6YMAInXn1JAfKx5bJCJJr+EnxEw9orsfXk3KGfPBC
+vWjzrUcm5oKvC08eCv5Na1w3ukaObQBOwGRp9QY8o046KtmR95V8RKUbtW9W1Ldp
+GOJDKHgSC0Os4urHxYpt11tx0u3jjzSphkE/+6F2SDGCza46huzdoYmdaY0d2F0S
+jiuve+6pfS8iCyMa05aHq35stWk1PWmtCYzzJXnmbWdMkadJNuQRJUyEOLQ3U2hp
+m+ZbJ9zjAgMBAAECggEAIQuCyxgAhfcoMh0QdCpCRdq0ayQhypE6w+RAywFwNjGF
+mLQuW9PeLCxAbzGDqIrWKeidY7TZPKRrswRymO2ExDNyYzZn0FbhaL3OJ4WZhF8P
+EdJDGlaV4mF6TsEoLudoPCGLsb1VUq1GgL7CisjNW1EEg0rVCXYrEaEBL+q4XVzm
+rdUFuui0qNNjSomVTMaiEjyziMQ3k1vKaMvXG8h3eO5O31z67Muy90T6eJ3nBq+3
+qbyfgnj3MAly1nKCQRA2IBW7by9beIz2pSz40u207d+PoCcv2/FMsXkuQ4jxji/m
+8VIz1jwd5cwBfMxjZ0hcXO1Nq06WfqHnOyF+zMlfEQKBgQD5XZP6L2+qrOtOIf0U
+eDWAGRBCLpc16nevQ7jaovHWdIqFiqZMdnELbpYerTT17XcJx/03EIl1x7P/TJA9
+OaMlDG5SoY9XcFTVieZgr0osqgFixi54EEB49HuzxWDj6BMwss39ntVSTAkRzJhx
+D9bY5tlCvEaQpFyGPpjfVv4+xwKBgQDGr2JqgTPgrH9mCeIYOr/GwqHWhBHoibT6
+f16oyLdnPtctvPAzZJ/cOVHCy0nssSuPR77pK7qb2cHW+n+txq23bhkCEeNkNn6m
+6yzNnG+fO9LKTm/oazqQle9UIaba4if0aIWoHl5tYbQZ//QVJpNAcMR/cwS4V4T0
+z/z9Q5NFBQKBgQCfyBdOYuDRYvVvXhX07MWTK/wf/AyFzpQb6G/lIC2HtasgwGOo
+cOgkZBqq018xCZSR3uRgSSdbIbgzKNLveCQSVDHInp7jbyXcofzNDOShU9mJeeVC
+p184Yad13E4mGolZVejpzsFvdysEja1MHNMUrm6d9VfdzINAvZFk4jAM9wKBgQCU
+NINfGt2NvF6TyM+Eb15abxi1oXKSWRZMvPHpST+1niR4k7VBQNAWQBODEI0mJ8ps
+aII6AEqEstxq9hSDle5DI7c32gwa1qOG82pKPWTuDHviOLw1TLc03wLVaPzDzWss
+X0ND8tNRGE52Dn0NweaZbQTGZQ+iSnZ8/yCh8uRJ2QKBgENPTd40kx9aP2r1/j+D
+ONBU8ky3MhoJ056aqYQGRIYCMCCqbXM3wXLgAN/x+75usjFz/iN8rbWcIQjw65nC
+SV8x721hl12U+JWvvmGV9owjGLK1pzYfdqa7ixkPO8/O3Uut48Mem/k5rSTxCTwT
+W+8UqBhoku6UbW3LTx5hJh4K
+-----END PRIVATE KEY-----

+ 60 - 0
config/ssl/local.newobj.org.pem

@@ -0,0 +1,60 @@
+-----BEGIN CERTIFICATE-----
+MIIE7TCCA9WgAwIBAgISA/3ZsdoAxQjKqccTsHCsEyu4MA0GCSqGSIb3DQEBCwUA
+MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
+EwJSMzAeFw0yNDA1MjgxNDAyMTBaFw0yNDA4MjYxNDAyMDlaMBsxGTAXBgNVBAMT
+EGxvY2FsLm5ld29iai5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDBiTdJOfaHJ0L4BYyiN+CF5uL82wFjfrn5evWwKZ6Ie0JxDkzG/okswhtwvU75
+g5uhWbWzdQR47EmPuGJnrw1apVOnzV9e6XuTc2o6YMAInXn1JAfKx5bJCJJr+Enx
+Ew9orsfXk3KGfPBCvWjzrUcm5oKvC08eCv5Na1w3ukaObQBOwGRp9QY8o046KtmR
+95V8RKUbtW9W1LdpGOJDKHgSC0Os4urHxYpt11tx0u3jjzSphkE/+6F2SDGCza46
+huzdoYmdaY0d2F0Sjiuve+6pfS8iCyMa05aHq35stWk1PWmtCYzzJXnmbWdMkadJ
+NuQRJUyEOLQ3U2hpm+ZbJ9zjAgMBAAGjggISMIICDjAOBgNVHQ8BAf8EBAMCBaAw
+HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYD
+VR0OBBYEFIAYfAsnvnBYyPfyH8teZNpOI/2RMB8GA1UdIwQYMBaAFBQusxe3WFbL
+rlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDov
+L3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5sZW5jci5v
+cmcvMBsGA1UdEQQUMBKCEGxvY2FsLm5ld29iai5vcmcwEwYDVR0gBAwwCjAIBgZn
+gQwBAgEwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdgB2/4g/Crb7lVHCYcz1h7o0
+tKTNuyncaEIKn+ZnTFo6dAAAAY+/uRqTAAAEAwBHMEUCIFFn3GO/G0kr8XhbTm0O
+bI08Pz6OzkvqGjcPDXJMmSUzAiEAsfrW5DVMPj/Uhm0f3oWGfRbvmUxj4xiwA+Q2
+h0sHGZIAdgDf4VbrqgWvtZwPhnGNqMAyTq5W2W6n9aVqAdHBO75SXAAAAY+/uRr+
+AAAEAwBHMEUCIExO427ffujJmSQzGq9EwnT7gfwvldQNH7wavYKJEP6HAiEAhaNl
+dfSMqepd+DCasm73LghCqKAmqcPU6STUkI6qi08wDQYJKoZIhvcNAQELBQADggEB
+AFNono1dy2oT+8p1q39n/WqdrdlcjnpT0ogzm+tKlvHFQnFadE35yCSV983AK4hE
+rzkHH07rVq82cHTK61n7KA1m6C4ZwS/wx8th6gdhDVMmEpYXT+oMmmK9pnsxoei1
+N6rDHNSXiEumqqk/cu/7aTwWT7Qjd4Hxzw8kvY6pCGx68OQxkjvBQkL0ZVSTNfrr
+IGgqgkouku+IhDDuiq4Kf7MNaWINQ+8mvQcxy8xjh8+DMcqxO+ThgjJhx5OTc4/K
+PjBh4B98Nv0t5w8ClWWP1yFXUggldfJGgjrPhjeK1tSb8zZQFZqfKWRvWRcClbiL
+GaOgdXDbz4ZDeFQRri+Cx9M=
+-----END CERTIFICATE-----
+
+-----BEGIN CERTIFICATE-----
+MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
+WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
+RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
+R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
+sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
+NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
+Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
+/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
+Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
+FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
+AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
+Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
+gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
+PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
+ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
+CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
+lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
+avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
+yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
+yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
+hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
+HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
+MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
+nLRbwHOoq7hHwg==
+-----END CERTIFICATE-----

+ 51 - 2
src/core/config.cpp

@@ -35,6 +35,15 @@ bool config::open(const std::string& ini_filepath)
 	cache();
 	return true;
 }
+bool config::have_https()
+{
+	for_iter(iter, domain)
+	{
+		if (iter->second.https)
+			return true;
+	}
+	return false;
+}
 std::vector<std::string> config::extractVariableNames(const std::string& text)
 {
 	std::regex pattern("\\$\\{([^}]+)\\}"); // 使用捕获组提取中间的内容
@@ -51,8 +60,6 @@ std::vector<std::string> config::extractVariableNames(const std::string& text)
 
 void config::cache()
 {
-	server.address =  m_ini.read("server", "address");
-	server.port = ylib::stoi(m_ini.read("server", "port"));
 
 	scripts.app_dir = m_ini.read("scripts","app_dir");
 	scripts.lib_dir = m_ini.read("scripts", "lib_dir");
@@ -67,6 +74,7 @@ void config::cache()
 	website.session_timeout_sec = ylib::stoi(m_ini.read("website", "session_timeout_sec"));
 	website.Initialization_script = m_ini.read("website", "Initialization_script");
 	website.debug = m_ini.read("website", "debug") == "1";
+	website.domain = ylib::json::from(m_ini.read("website", "domain")).to<std::vector<std::string>>();
 
 	{
 		ylib::json interceptors = ylib::json::from(m_ini.read("website", "interceptor_scripts"));
@@ -83,4 +91,45 @@ void config::cache()
 			website.interceptor_scripts.push_back(inr);
 		}
 	}
+
+	// website 域名参数
+	for(size_t i=0;i< website.domain.size();i++)
+	{
+		if (website.domain[i].empty())
+			continue;
+
+		struct config::domain dm;
+		dm.port = ylib::stoi(m_ini.read(website.domain[i], "port"));
+		dm.https = m_ini.read(website.domain[i],"https")=="1";
+		dm.ssl.pem_key = ylib::file::read(m_ini.read(website.domain[i], "ssl_key"));
+		dm.ssl.pem_cert = ylib::file::read(m_ini.read(website.domain[i], "ssl_pem"));
+		dm.ssl.pem_ca = ylib::file::read(m_ini.read(website.domain[i], "ssl_ca"));
+		dm.ssl.pem_password = m_ini.read(website.domain[i], "ssl_pwd");
+		dm.ssl.type = (network::http::ssl_verify_type)ylib::stoi(m_ini.read(website.domain[i], "ssl_ver_type"));
+		if (dm.port == 0)
+		{
+			LOG_ERROR("domain("+website.domain[i] + ") name unavailable, port is 0");
+			continue;
+		}
+		if (dm.https)
+		{
+			dm.ssl.enable = true;
+			if (dm.ssl.pem_key.empty())
+			{
+				LOG_ERROR("domain(" + website.domain[i] + ") ssl_key file is read as empty, please check the ssl_key");
+				continue;
+			}
+			if (dm.ssl.pem_cert.empty())
+			{
+				LOG_ERROR("domain(" + website.domain[i] + ") ssl_pem file is read as empty, please check the ssl_pem");
+				continue;
+			}
+			if (dm.ssl.type < 0 || dm.ssl.type > 3)
+			{
+				LOG_ERROR("domain(" + website.domain[i] + ") ssl_ver_type is not filled in correctly, it should be: 0~3");
+				continue;
+			}
+		}
+		domain.emplace(website.domain[i],dm);
+	}
 }

+ 14 - 5
src/core/config.h

@@ -3,8 +3,14 @@
 #include "base/error.h"
 #include "base/singleton.hpp"
 #include "util/ini.h"
+#include "net/http_define.h"
 class config:public ylib::error_base,public ylib::singleton<config>{
 public:
+	struct domain {
+		bool https = false;
+		ushort port = 0;
+		network::http::ssl_config ssl;
+	};
 	struct scripts {
 		std::string app_dir;
 		std::string lib_dir;
@@ -25,14 +31,17 @@ public:
 		std::string Initialization_script;
 		std::vector<__interceptor> interceptor_scripts;
 		bool debug = false;
-	};
-	struct server {
-		std::string address;
-		ushort port = 0;
+		std::vector<std::string> domain;
 	};
 public:
 	config() = default;
 	bool open(const std::string& ini_filepath);
+
+	/// <summary>
+	/// 是否含有https
+	/// </summary>
+	/// <returns></returns>
+	bool have_https();
 private:
 	// INI配置文件
 	ylib::ini m_ini;
@@ -50,5 +59,5 @@ private:
 public:
 	scripts scripts;
 	website website;
-	server server;
+	std::map<std::string, domain> domain;
 };

+ 17 - 7
src/core/fastweb.cpp

@@ -24,26 +24,36 @@ bool fastweb::start()
 	m_center = new network::http::center();
 	network::http::start_config config;
 	network::http::website_config ws_config;
-	network::http::host_config host_config;
-	host_config.domain = "0.0.0.0";
-	host_config.port =(ushort)sConfig->server.port;
-
-	host_config.ssl = false;
+	
+	for_iter(iter, sConfig->domain)
+	{
+		network::http::host_config host_config;
+		host_config.domain = iter->first;
+		host_config.port = iter->second.port;
+		host_config.ssl = iter->second.https;
+		ws_config.host.push_back(host_config);
+	}
 
 	ws_config.name = "master";
-	ws_config.host.push_back(host_config);
+	
 	ws_config.router.threadpool.size = 40;
 	ws_config.router.threadpool.queuemax = 10000;
 	ws_config.session.dirpath = sConfig->website.session_dir;
 	ws_config.session.timeout_sec = sConfig->website.session_timeout_sec;
 	config.website.push_back(ws_config);
+	for_iter(iter, sConfig->domain)
+	{
+		if(iter->second.https) 
+			config.cert.emplace(iter->first, iter->second.ssl);
+	}
+
 	if (!m_center->create(config))
 	{
 		m_lastErrorDesc = "start failed," + m_center->last_error();
 		stop();
 		return false;
 	}
-	auto website = m_center->website(sConfig->server.address);
+	auto website = m_center->website_byname(ws_config.name);
 	auto router = website->router();
 	
 	// 初始化脚本