为网站增加PWA支持实现原生应用体验
序 前些时间用Web写了一个简单的物联网控制程序，本来想是不是需要打包成APP然后发布。后来发现了PWA能够直接将网页添加到各种设备中来实现原生应用的功能如发送通知、离线查看、渐进式加载等。PWA可以将各类网页都“打包”成原生应用，包括单一网页或者Typecho博客，以下，将会拿本博客举例实现PWA的简单应用。 什么是PWA(渐进式 Web 应用) PWA（Progressive Web Apps，渐进式 Web 应用）运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序。这些应用无处不在、功能丰富，使其具有与原生应用相同的用户体验优势。PWA 是可被发现、易安装、可链接、独立于网络、渐进式、可重用、响应性和安全的。 简单理解，PWA可以将Web应用转化成能够在多平台设备上使用的原生应用程序并且具有和原生应用接近的交互体验，无需下载直接安装。 注意：PWA并不是一种单独的技术，而是多项Web技术集成的Web App，其核心技术包括App Manifest、Service Worker、Web Push等。 快速为网站配置PWA 以下将简单阐述如何快速为网站添加PWA支持，内容较为简单且没有发挥出PWA的全部功能，若需要更深入研究请见文末的拓展阅读。 配置HTTPS Service Worker必须运行在HTTPS或本地环境下，所以开启PWA的前提是配置好站点的HTTPS！！！在这里不再赘述。 制作应用图片 PWA需要为APP注册一个ICON，这里使用和网站favicon相同的图标，并且推荐将图片的分辨率保证在256x256以上！ 配置Manifest Manifest是一份用JSON记录网站信息的清单，其中包含了应用的标题、图标的大小与路径、加载页的背景颜色等，只有编写了这份清单浏览器才能正确处理Web App信息。在编写Manifest时会发现有不同拓展名，如manifest.webapp、manifest.json，但是在W3C规范中规定了其标准拓展名应为.webmanifest以下是我编写的一份Manifest示例： { "background_color": "#fff", //Web App启动时的背景颜色，可以使用预设的一些颜色名字如red,blue等，或者直接使用HEX颜色值如#66ccff(天依蓝) "description": "Describe your site.", //Web App的描述，这里的内容将会在安装时展现 "display": "fullscreen", //Web App展示的方式，可选的值有fullscreen,standalone,minimal-ui,browser等，具体含义请见文末拓展阅读 "icons": [ { "src": "icon.png", "sizes": "192x192", "type": "image/png" } ], //这里举例了应用图片的配置，可以配置多个图标！ "name": "Awesome fox pictures", //应用的名称，在安装时展示 "short_name": "Foxes", //缩略名，一般在添加到桌面之后会展示这个名字 "start_url": "/" //启动后进入的 } 然后将本文件保存为manifest.webmanifest并放置在网站根目录，并在网站 标签内添加以下内容： Safari浏览器对PWA支持并不完善，如果需要正确的展示PWA应用，需要将以下代码根据实际情况调整后添加在 标签内： 注册Service Worker实现A2HS 我们需要Service Worker来处理安装A2HS(Add to Home screen)与缓存事件，通常情况下A2HS事件会由浏览器自行处理，但是某些情况下我们想要自己控制这个行为来引导用户安装PWA应用。 首先编写index.js，这部分内容也可以直接编写在网页的 标签中。 // 注册Service Worker来使网站离线工作 if ('serviceWorker' in navigator) { navigator.serviceWorker .register('/sw.js') //Service Worker文件路径 .then(() => { console.log('Service Worker Registered'); }); } // 提醒用户安装PWA应用,如果您不想这样，可以直接使用showInstallPromotion(); let deferredPrompt; const addBtn = document.querySelector('.add-button'); addBtn.style.display = 'none'; window.addEventListener('beforeinstallprompt', (e) => { // 防止Chrome 67以前版本的浏览器出现此提醒 e.preventDefault(); //阻止自动提示，若想将A2HS的控制权交给浏览器则请注释 deferredPrompt = e; // 显示安装提醒按钮 addBtn.style.display = 'inline'; addBtn.addEventListener('click', () => { // 隐藏提示按钮 addBtn.style.display = 'none'; // 显示安装提示 deferredPrompt.prompt(); deferredPrompt.userChoice.then((choiceResult) => { if (choiceResult.outcome === 'accepted') { console.log('User accepted the A2HS prompt'); } else { console.log('User dismissed the A2HS prompt'); } deferredPrompt = null; }); }); }); 此时我们需要在 内有一个用来提示安装的按钮，示例代码如下： 将网页添加到桌面 接下来是Service Worker的代码，将其命名为sw.js并保存。 self.addEventListener('install', (e) => { e.waitUntil( caches.open('store').then((cache) => cache.addAll([ '/', '/index.html', //需要缓存的静态资源 ])), ); }); self.addEventListener('fetch', (e) => { console.log(e.request.url); e.respondWith( caches.match(e.request).then((response) => response || fetch(e.request)), ); }); //处理fetch事件 成果展示 拓展阅读 Progressive Web Apps Add a web app manifest 让 PWA 易于安装 - 渐进式 Web 应用（PWA） | MDN Add to Home screen 添加到主屏幕 - 渐进式 Web 应用（PWA） | MDN 渐进式 Web 应用（PWA）| MDN 《PWA 应用实战》 Web app manifests
一些常用的设计相关素材与工具网站
序 以下是个人常用的一些美术设计相关素材与工具网站。 插画类 unDraw.co 一个优秀的免费插画网站，可以自定义插画颜色并支持下载SVG与PNG格式图片。 地址：https://undraw.co/ Delesign 优秀的插画与图标库，素材可免费商用，支持PNG与SVG格式下载。 地址：https://delesign.com/free-designs/graphics/ manypixels 也是免费且可自定义色彩，筛选功能也比以上两款好用，支持SVG与PNG图片下载。缺点是画风不统一。 地址：https://www.manypixels.co/gallery Humaaans 人物插画生成器，支持自定义人物的各种部分与动作！ 地址：https://www.humaaans.com/ Scenic Background Animations 60+风景插画合集，不同插画分别带有不同时段的图片，并且可以一键下载全套插图，真的有被其画风惊艳到。 地址：https://www.pixeltrue.com/scenic-illustrations 图标类 ICONFONT 阿里巴巴旗下图标库，非常好用。 地址：https://www.iconfont.cn/ ICONS8 丰富的素材站，支持图标、插画等各样设计素材下载。 地址：https://icons8.com/ 背景图 图鱼 大量好用的背景纹理素材。 地址：https://www.hituyu.com/ Cool Backgrounds 支持五种样式的背景生成器，样式较少不太实用。 地址：https://coolbackgrounds.io/ Wicked Backgrounds 波浪背景生成器，功能强大。 地址：https://wickedbackgrounds.com/ Haikei 功能丰富多样的背景生成工具，支持随机生成手残党福音。 地址：https://app.haikei.app/ 色彩 Picular 输入任意字符自动生成相关色卡，非常强大且解决配色难题。 地址：https://picular.co/ 100 Mesh Gradients 提供100张渐变图片素材，可以打包下载，果风浓浓！ 地址：https://www.meshgradients.design/ Mesh 支持自定义生成美丽的渐变图片。 地址：https://meshgradient.com/ 工具类 Pixel Map Generator 万能的地图生成器，在使用此工具时要注意政治相关问题！ 地址：https://pixelmap.amcharts.com/ Removebg 快速高效的抠图工具，非注册用户可以下载到的图片也拥有不错的画质。 创客贴抠图 国内的快速抠图工具，需要登录注册。质量也非常高。 Bigjpg 图片无损放大工具，支持API可以进行二次开发！ Img.top 图片无损压缩工具，支持jpg,png,gif格式。最大支持单文件5M. DocSmall 文件无损压缩工具，支持jpg,png,gif,pdf格式。最大支持单文件25M. Toools.design 设计资源收集网站，包括设计需要使用的各种资源。 CodeToImg 将代码转换成图片，支持PNG,JPG,SVG等多种格式。程序开源可自部署！
在宝塔下使用ngx_waf增强WAF防护性能/防CC/开启5秒盾
序 由于曾经被黑恶势力痛揍过，至今对CC Flood无法释怀以至于产生了PTSD。每次装网站都会好好折腾一下软防来尽量减少被攻击的损失(虽然我的孤岛并不会有人造访) 。事实上，DDoS防御是一项系统工程，且更多体现在资源的较量上。针对网络层的攻击拼带宽与流量，针对七层的攻击则拼架构与性能。真正在部署DDoS防御时，运营商与机房级别的硬件防御才是真正的主力，但是其费用之高昂不是一般用户所能承担。于是部署在应用层的软防成为大多数建站者的选择。 众所周知，宝塔面板有商用的Nginx防火墙插件（要钱），具有丰富的WAF(Web Application Firewall)功能，但是其防CC能力在面对攻击时形同虚设，使用简单的CC工具就可以轻松实现503 Page。而较老的httpguard、ngx_lua_waf等均已年久失修。偶然间在Github上发现了ngx_waf后折腾了一下发现确实不错。 NGX_WAF简介 方便且高性能的 Nginx 防火墙模块。(以下内容来自原项目介绍) 为什么选择 ngx_waf 功能齐全：「网络应用防火墙」的基本功能都有。 安装方便：大多数情况下你可以直接下载使用预构建的模块，而不是编译代码。 使用方便：配置指令简单易懂，不用看文档都能猜到大概是什么意思。 规则灵活：提供高级规则，将动作（如拦截或放行）和多个条件表达式组合起来。 高性能：经过较为极限的测试，启动本模块后 RPS（每秒请求数） 降低约 4%。测试说明和结果见使用文档。 功能 SQL 注入防护（Powered By libinjection）。 XSS 攻击防护（Powered By libinjection）。 支持 IPV4 和 IPV6。 CC 防御，超出限制后自动拉黑对应 IP 一段时间。 IP 黑白名单，同时支持类似 192.168.0.0/16 和 fe80::/10，即支持点分十进制和冒号十六进制表示法和网段划分。 POST 黑名单。 URL 黑白名单 查询字符串（Query String）黑名单。 UserAgent 黑名单。 Cookie 黑名单。 Referer 黑白名单。 高级规则，将动作（如拦截或放行）和多个条件表达式组合起来。 相关链接 使用文档：https://docs.addesp.com/ngx_waf/zh-cn/ GitHub：https://github.com/ADD-SP/ngx_waf 总结 一个用C构建的高效率Nginx防火墙，开发者积极维护(在写稿的时候就更新了3个版本导致不得不反复修改)，并且支持开启5秒盾，实测抗CC性能优秀！ 安装 以下内容源于官方文档和自己的折腾记录，仅供参考！ 环境 CentOS 7 Nginx 1.21.0 宝塔 7.6.0 ngx_waf v7.0.0 Current 如果您的环境与我相同，以下安装指令可以照抄，反之请自行检查相关指令。 安装过程 首先创建临时的工作目录，并将项目拷贝到本地。 mkdir /root/nginx #临时工作目录，这个在后面会用到 cd /root/nginx git clone https://github.com/ADD-SP/ngx_waf.git #获取最新版本的ngx_waf，也可以直接去Release找以往的版本 cd ngx_waf git clone https://github.com/libinjection/libinjection.git inc/libinjection nginx 提供两种安装模块的方式，即「静态链接」和「动态加载」，通过两种方式安装的模块也分别称为「静态模块」和「动态模块」。 你可以通过运行脚本 assets/guide.sh 来选择使用静态模块还是动态模块。 sh assets/guide.sh # It is recommended that you use dynamic modules. # 如果输出上面这行则建议使用动态模块。 # It is recommended that you use static modules. # 如果输出上面这行则建议使用静态模块。 在宝塔环境下得到的推荐是静态模块，实际在折腾过文章介绍的动态模块后均会出现奇怪的错误，于是在后文介绍的是静态模块安装。 到这一步我们需要开始进行编译，这里可能会涉及各种依赖问题如gcc等，由于不同环境的依赖问题不一样，这里就不再赘述，请自行通过搜索引擎解决。 在搞定依赖问题后需要获取当前nginx的configure 脚本的参数，在宝塔环境下输入以下指令即可获得。 /www/server/nginx/sbin/nginx -V 得到以下内容，这里将configure arguments: 后面的内容记录下来，并在结尾加上--add-module=/usr/local/src/ngx_waf即可得到编译参数。如果您使用的编译器是 GCC，请在 --with-cc-opt 中追加 -fstack-protector-strong， 例如 --with-cc-opt='-Werror -g' ---> --with-cc-opt='-Werror -g -fstack-protector-strong'。 nginx version: nginx/1.21.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) built with OpenSSL 1.1.1k 25 Mar 2021 TLS SNI support enabled configure arguments: --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module --with-cc-opt=-std=gnu99 接下来开始编译ngx_waf模块与nginx，以下代码会用到上述处理好的编译参数。 cd /root/nginx/ngx_waf make cd /www/server/nginx/src ./configure --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module --add-module=/root/nginx/ngx_waf --with-cc-opt='-std=gnu99' make mv ../sbin/nginx ../sbin/nginx.bak cp ./objs/nginx ../sbin/nginx chmod +x /www/server/nginx/sbin/nginx 到这里就已经替换原有的Nginx程序，接下来在宝塔中启动Nginx即可！ 若您出现如下报错： nginx: the configuration file /www/server/nginx/conf/nginx.conf syntax is ok nginx: configuration file /www/server/nginx/conf/nginx.conf test failed 则需要先卸载宝塔的Nginx防火墙再重新安装！ 到此为止，安装与编译结束。 配置 在安装完成后我们可以将配置文件加入单个站点的配置文件中以实现未不同网站定制不同的规则，配置填写位置如图： 以下介绍我的配置，内容并不完善，各参数与各模块具体功能请详见参考文档！ waf on; # 是否启用模块 waf_rule_path /root/nginx/ngx_waf/assets/rules/; # 模块规则 waf_mode DYNAMIC; # 启用动态网站模式 waf_cache capacity=100; # 设置缓存规则检查结果相关的参数，过小会导致频繁地淘汰缓存，增加内存碎片，降低性能 waf_under_attack on file=/www/wwwroot/defence.html; # 对所有访问的用户开启5秒盾，file需要填写单个html的绝对路径！请仅在网站遭受大量攻击的时候打开！其中该html的作用为5秒之后刷新页面！ waf_cc_deny rate=300r/m duration=10m size=20m; #每分钟请求大于300次则封禁10分钟，最多缓存20M大小的请求记录 如果使用CDN或负载均衡等反向代理程序，为获取真实的客户IP地址，需要用到http_realip_module，宝塔的Nginx已经默认编译该模块。此时我们需要在配置文件中加入： set_real_ip_from 0.0.0.0/0; #CDN节点的IP段，此项可多次申明，请根据实际情况填写，照抄危险！ real_ip_header X-Forwarded-For; 以上提到了用于5秒盾跳转的HTML页面，以下是我自己的一个版本，仅供参考。 正在检查您的浏览器... OOPS! 站点正在被攻击！您的请求正在接受检查... 请给我们一些时间，您马上就会回到站点，这会很快~ 将以上内容保存到/www/wwwroot/defence.html即可。 测试 访问 /www.bak，如果返回 403 状态码则表示模块成功启动。 结语 至此ngx_waf模块安装结束，在配置好一定的防御策略之后可以获得不错的防御能力。