|
@@ -0,0 +1,195 @@
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 443 ssl;
|
|
|
|
|
+ http2 on;
|
|
|
|
|
+ server_name _;
|
|
|
|
|
+
|
|
|
|
|
+ # SSL证书路径
|
|
|
|
|
+ ssl_certificate /usr/local/openresty/nginx/ssl/ali.haijunit.icu.pem;
|
|
|
|
|
+ ssl_certificate_key /usr/local/openresty/nginx/ssl/ali.haijunit.icu.key;
|
|
|
|
|
+
|
|
|
|
|
+ ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
|
+ ssl_ciphers 'EECDH+AESGCM:EECDH+CHACHA20:EECDH+AES256:!aNULL:!MD5:!RC4';
|
|
|
|
|
+ ssl_prefer_server_ciphers on;
|
|
|
|
|
+ ssl_session_cache shared:SSL:50m;
|
|
|
|
|
+ ssl_session_timeout 10m;
|
|
|
|
|
+
|
|
|
|
|
+ ssl_stapling on;
|
|
|
|
|
+ ssl_stapling_verify on;
|
|
|
|
|
+
|
|
|
|
|
+ # 可选:显式指定 TLSv1.3 cipher(仅 OpenSSL 1.1.1+ 支持)
|
|
|
|
|
+ ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
|
|
|
|
|
+
|
|
|
|
|
+ # 安全 Header
|
|
|
|
|
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
|
|
|
+ add_header X-Frame-Options SAMEORIGIN;
|
|
|
|
|
+ add_header X-Content-Type-Options nosniff;
|
|
|
|
|
+ add_header X-XSS-Protection "1; mode=block";
|
|
|
|
|
+ add_header Content-Security-Policy "default-src 'self' data: blob: https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:;" always;
|
|
|
|
|
+
|
|
|
|
|
+ root html;
|
|
|
|
|
+ try_files $uri $uri/ /index.html;
|
|
|
|
|
+
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 通用业务
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ location = / {
|
|
|
|
|
+ rewrite ^/ /course break;
|
|
|
|
|
+ }
|
|
|
|
|
+ # lua 文件上传接口
|
|
|
|
|
+ location = /api/upload {
|
|
|
|
|
+ content_by_lua_file /usr/local/openresty/lua/file_upload.lua;
|
|
|
|
|
+ }
|
|
|
|
|
+ # lua 读取json文件
|
|
|
|
|
+ location /api/json/ {
|
|
|
|
|
+ content_by_lua_file /usr/local/openresty/lua/query_json.lua;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 前端应用
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ location / {
|
|
|
|
|
+ index index.html;
|
|
|
|
|
+ try_files $uri $uri/ /index.html;
|
|
|
|
|
+ expires 7d;
|
|
|
|
|
+ add_header Cache-Control "public, max-age=604800, immutable";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 静态资源缓存 + 防盗链
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ location ~* \.(js|css|png|jpg|jpeg|gif|svg|woff2?|ttf|ico)$ {
|
|
|
|
|
+ expires 30d;
|
|
|
|
|
+ access_log off;
|
|
|
|
|
+ add_header Cache-Control "public, max-age=2592000, immutable";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # OSS 静态目录(带目录索引)
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ location ^~ /oss/ {
|
|
|
|
|
+ alias /opt/oss/;
|
|
|
|
|
+ index _; # 去掉默认的界面
|
|
|
|
|
+ autoindex on; # 开启目录索引
|
|
|
|
|
+ autoindex_exact_size off; # 文件大小人性化显示
|
|
|
|
|
+ autoindex_localtime on; # 显示本地时间
|
|
|
|
|
+ charset utf-8;
|
|
|
|
|
+ expires 30d;
|
|
|
|
|
+ add_header Cache-Control "public, max-age=2592000, immutable";
|
|
|
|
|
+ # 如果不做这个配置,点击目录下的txt文件,大部分浏览器默认是直接浏览的。这里通过添加响应头来控制。
|
|
|
|
|
+ if ($request_filename ~* ^.*?\.(html|txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|conf)$){
|
|
|
|
|
+ add_header Content-Disposition 'attachment;';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 课程管理
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ location ^~ /course/ {
|
|
|
|
|
+ alias /opt/course/;
|
|
|
|
|
+ index index.html;
|
|
|
|
|
+
|
|
|
|
|
+ # 安全头部配置
|
|
|
|
|
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
|
|
|
|
|
+ add_header X-Content-Type-Options nosniff;
|
|
|
|
|
+ add_header X-XSS-Protection "1; mode=block";
|
|
|
|
|
+ add_header Referrer-Policy "same-origin";
|
|
|
|
|
+
|
|
|
|
|
+ add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()";
|
|
|
|
|
+ add_header Content-Security-Policy "default-src 'self'; worker-src 'self' blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; connect-src 'self' https:; font-src 'self' data: https:; frame-ancestors 'self'";
|
|
|
|
|
+
|
|
|
|
|
+ try_files $uri $uri/ /course/index.html;
|
|
|
|
|
+ }
|
|
|
|
|
+ location = /course/api/device/status {
|
|
|
|
|
+
|
|
|
|
|
+ # 允许所有域名跨域
|
|
|
|
|
+ add_header 'Access-Control-Allow-Origin' '*';
|
|
|
|
|
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
|
|
|
|
+ add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
|
|
|
|
|
+ add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
|
|
|
|
|
+
|
|
|
|
|
+ default_type application/json;
|
|
|
|
|
+ content_by_lua_file /usr/local/openresty/lua/course_device_status.lua;
|
|
|
|
|
+ }
|
|
|
|
|
+ location ^~ /course/api/ {
|
|
|
|
|
+ default_type application/json;
|
|
|
|
|
+
|
|
|
|
|
+ add_header 'Access-Control-Allow-Origin' '*' always;
|
|
|
|
|
+ add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
|
|
|
|
|
+ add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
|
|
|
|
|
+ add_header 'Access-Control-Allow-Credentials' 'true' always;
|
|
|
|
|
+
|
|
|
|
|
+ # 移除 rewrite,改用 proxy_pass 直接处理
|
|
|
|
|
+ proxy_pass http://124.222.28.5:7213/;
|
|
|
|
|
+
|
|
|
|
|
+ proxy_set_header Host m1.apifoxmock.com;
|
|
|
|
|
+ proxy_set_header X-Real-IP $remote_addr;
|
|
|
|
|
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
|
|
|
+ proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
|
+
|
|
|
|
|
+ # 处理代理失败的情况(如404)
|
|
|
|
|
+ proxy_intercept_errors on;
|
|
|
|
|
+ error_page 404 = @course_api_fallback;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ location @course_api_fallback {
|
|
|
|
|
+ default_type application/json;
|
|
|
|
|
+ content_by_lua_block {
|
|
|
|
|
+ local uri = ngx.var.uri
|
|
|
|
|
+
|
|
|
|
|
+ if uri:find("^/course/api/system/dict") then
|
|
|
|
|
+ -- 字典相关接口
|
|
|
|
|
+ local dict = require "course_dict"
|
|
|
|
|
+ dict.handle(uri)
|
|
|
|
|
+ else
|
|
|
|
|
+ -- 其他接口走 mock
|
|
|
|
|
+ local mock_router = require "course_mock"
|
|
|
|
|
+ mock_router("/course/api")
|
|
|
|
|
+ end
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 健康检查
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ location /health {
|
|
|
|
|
+ access_log off;
|
|
|
|
|
+ return 200 'healthy';
|
|
|
|
|
+ add_header Content-Type text/plain;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 错误页
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ error_page 403 /403.html;
|
|
|
|
|
+ error_page 404 /404.html;
|
|
|
|
|
+ error_page 500 502 503 504 /50x.html;
|
|
|
|
|
+
|
|
|
|
|
+ location = /403.html {
|
|
|
|
|
+ }
|
|
|
|
|
+ location = /404.html {
|
|
|
|
|
+ }
|
|
|
|
|
+ location = /50x.html {
|
|
|
|
|
+ }
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 安全配置
|
|
|
|
|
+ #-------------------------------------------------
|
|
|
|
|
+ # 安全配置:禁止访问隐藏文件
|
|
|
|
|
+ location ~ /\. {
|
|
|
|
|
+ deny all;
|
|
|
|
|
+ access_log off;
|
|
|
|
|
+ log_not_found off;
|
|
|
|
|
+ }
|
|
|
|
|
+ # 安全配置:禁止访问常见敏感文件
|
|
|
|
|
+ location ~* (\.log|\.sql|\.env|\.git) {
|
|
|
|
|
+ deny all;
|
|
|
|
|
+ access_log off;
|
|
|
|
|
+ log_not_found off;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+#=====================================================
|
|
|
|
|
+# HTTP -> HTTPS 自动跳转
|
|
|
|
|
+#=====================================================
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 80;
|
|
|
|
|
+ server_name _;
|
|
|
|
|
+ return 301 https://$host$request_uri;
|
|
|
|
|
+}
|