cms 网站后台内容管理系统模板

cms 网站后台内容管理系统模板

教程:cms网站后台内容管理系统模板更新:免费blog后台搭建

网站优化优采云 发表了文章 • 0 个评论 • 103 次浏览 • 2022-09-24 09:13 • 来自相关话题

  教程:cms网站后台内容管理系统模板更新:免费blog后台搭建
  cms网站后台内容管理系统模板更新:php下载地址:免费blog后台搭建课程:【工具】-传智播客-全网营销传播第一it教育平台
  免费的。我觉得最主要的是要看你是为了什么,如果是为了提高排名那确实还可以弄一个学院系统之类的。你要不想收费也可以。别的平台都需要登录。你不用怕。
  
  虽然是免费的。但是肯定会存在很多问题,花两三万弄不了什么东西。
  个人觉得,可以先买个域名,然后买个二级域名做起来。然后找一个免费的写一个网站就好了,别人可能花钱找你做你就说有点太贵了。
  
  目前来说,微型不收费的基本上都收费,收费的一般都不咋的,买大型的太贵,二三万也不便宜,买小型的又没安全感。实在不行花两三万买个四位数域名也是够的,然后注册一个空间。
  推荐使用优易云微型web2.0,这个web2.0平台免费注册,免费试用,体验成功可免费使用半年,使用免费开通后可开通更多功能。安全:一个人或几个人注册一个账号就可以实现服务器开通、免费部署和使用,不涉及独立的服务器,安全易控制。方便:运行安全可靠,网站访问方便,多人同时登录无负载。操作简单、使用方便。
  多人共享域名和网站内容。易于维护:免费发布,免费编辑,免费发布域名管理记录,域名备案,免费管理与维护网站内容。精准推送:根据自己的网站属性智能推送。可快速被访问到。便捷开通:支持邮箱注册,快速开通网站内容,快速管理网站。可以长期免费合作。 查看全部

  教程:cms网站后台内容管理系统模板更新:免费blog后台搭建
  cms网站后台内容管理系统模板更新:php下载地址:免费blog后台搭建课程:【工具】-传智播客-全网营销传播第一it教育平台
  免费的。我觉得最主要的是要看你是为了什么,如果是为了提高排名那确实还可以弄一个学院系统之类的。你要不想收费也可以。别的平台都需要登录。你不用怕。
  
  虽然是免费的。但是肯定会存在很多问题,花两三万弄不了什么东西。
  个人觉得,可以先买个域名,然后买个二级域名做起来。然后找一个免费的写一个网站就好了,别人可能花钱找你做你就说有点太贵了。
  
  目前来说,微型不收费的基本上都收费,收费的一般都不咋的,买大型的太贵,二三万也不便宜,买小型的又没安全感。实在不行花两三万买个四位数域名也是够的,然后注册一个空间。
  推荐使用优易云微型web2.0,这个web2.0平台免费注册,免费试用,体验成功可免费使用半年,使用免费开通后可开通更多功能。安全:一个人或几个人注册一个账号就可以实现服务器开通、免费部署和使用,不涉及独立的服务器,安全易控制。方便:运行安全可靠,网站访问方便,多人同时登录无负载。操作简单、使用方便。
  多人共享域名和网站内容。易于维护:免费发布,免费编辑,免费发布域名管理记录,域名备案,免费管理与维护网站内容。精准推送:根据自己的网站属性智能推送。可快速被访问到。便捷开通:支持邮箱注册,快速开通网站内容,快速管理网站。可以长期免费合作。

网站制作多少钱?

网站优化优采云 发表了文章 • 0 个评论 • 80 次浏览 • 2022-09-05 07:09 • 来自相关话题

  网站制作多少钱?
  php开源建站系统管家为企业和个人提供大量网页模板,网站模板,企业网站模板,我们还为用户提供了完整的CMS系统,cms内容管理系统,php开源建站系统,我们还承接web前端开发,php开发网站定制开发业务,为满足大部分客户需求,我们提供了上千种免费网页模板下载尽在php开源建站系统管家平台,如何网站模板无法满足你的需要可以联系php开源建站系统管家我们为你定制开发
  襄阳做网站公司有哪些?
  
  湖北速建时代网络科技有限公司,是一家专业做网站公司,主要业务:网站定制开发,网站设计制作,前后端开发,app开发,小程序开发,小程序商城开发,pc端商城开发等业务
  我们有成熟的网站后台和强大的网站模板库,便于用户选择,有多套建站方案供用户选择
  网站制作多少钱
  我们提供模板建站 100元起
  
  我们提供定制开发 3500元起
  我们提供前端定制开发 价格更功能待定价格
  我们承接前端外部业务 价格更功能待定价格
  我们承接小程序开发业务 价格更功能待定价格 查看全部

  网站制作多少钱?
  php开源建站系统管家为企业和个人提供大量网页模板,网站模板,企业网站模板,我们还为用户提供了完整的CMS系统,cms内容管理系统,php开源建站系统,我们还承接web前端开发,php开发网站定制开发业务,为满足大部分客户需求,我们提供了上千种免费网页模板下载尽在php开源建站系统管家平台,如何网站模板无法满足你的需要可以联系php开源建站系统管家我们为你定制开发
  襄阳做网站公司有哪些?
  
  湖北速建时代网络科技有限公司,是一家专业做网站公司,主要业务:网站定制开发,网站设计制作,前后端开发,app开发,小程序开发,小程序商城开发,pc端商城开发等业务
  我们有成熟的网站后台和强大的网站模板库,便于用户选择,有多套建站方案供用户选择
  网站制作多少钱
  我们提供模板建站 100元起
  
  我们提供定制开发 3500元起
  我们提供前端定制开发 价格更功能待定价格
  我们承接前端外部业务 价格更功能待定价格
  我们承接小程序开发业务 价格更功能待定价格

cms网站后台内容管理系统模板规格后台需求分析库存系统

网站优化优采云 发表了文章 • 0 个评论 • 120 次浏览 • 2022-09-04 21:05 • 来自相关话题

  cms网站后台内容管理系统模板规格后台需求分析库存系统
  cms网站后台内容管理系统模板规格后台需求分析库存系统计划系统购物车系统退换货管理系统收银系统营销系统活动系统导购系统财务系统销售系统seo系统
  后台一般都可以使用现成的,比如discuzcms,或者博客程序。前端最简单的是自己做,把后台整合进去,实现一套框架,然后把各项需求集成到框架上。一般都没有固定的模板,需要根据需求来。
  
  我目前知道的,都是外包给代理商,要看方案!例如先做网站公司,做好后台后,
  你可以上cms商用建站平台,上面的功能齐全,模板多,
  发布贴吧来看看有没有高手整理出来
  
  网上很多优秀的后台还是可以参考的,不过有些因为是按整站走的,
  国内外好多大的cms都可以利用系统自带模板套用做的,还是看需求,
  我们也做后台,我们通过项目经理推荐,公司里各部门推荐了几家开发公司。后来选了一家外包公司。网站程序还是要看需求。后台市场上好多都是现成的cms软件。如果你需要后台集成的功能,那么建议你直接找一个模板定制的开发公司比较好,因为从大的方面来说,开发公司制作产品容易,专业的就难了。一定要注意。这也看你需要网站的数据需要以何种形式导出。
  建议从收集了解对方建站产品与网站数据库的对接。前端易搭你可以考虑一下,我们在电商的代工工厂,然后专业做电商项目。总体来说后台开发也就那些。你需要后台很简单。 查看全部

  cms网站后台内容管理系统模板规格后台需求分析库存系统
  cms网站后台内容管理系统模板规格后台需求分析库存系统计划系统购物车系统退换货管理系统收银系统营销系统活动系统导购系统财务系统销售系统seo系统
  后台一般都可以使用现成的,比如discuzcms,或者博客程序。前端最简单的是自己做,把后台整合进去,实现一套框架,然后把各项需求集成到框架上。一般都没有固定的模板,需要根据需求来。
  
  我目前知道的,都是外包给代理商,要看方案!例如先做网站公司,做好后台后,
  你可以上cms商用建站平台,上面的功能齐全,模板多,
  发布贴吧来看看有没有高手整理出来
  
  网上很多优秀的后台还是可以参考的,不过有些因为是按整站走的,
  国内外好多大的cms都可以利用系统自带模板套用做的,还是看需求,
  我们也做后台,我们通过项目经理推荐,公司里各部门推荐了几家开发公司。后来选了一家外包公司。网站程序还是要看需求。后台市场上好多都是现成的cms软件。如果你需要后台集成的功能,那么建议你直接找一个模板定制的开发公司比较好,因为从大的方面来说,开发公司制作产品容易,专业的就难了。一定要注意。这也看你需要网站的数据需要以何种形式导出。
  建议从收集了解对方建站产品与网站数据库的对接。前端易搭你可以考虑一下,我们在电商的代工工厂,然后专业做电商项目。总体来说后台开发也就那些。你需要后台很简单。

cms网站后台内容管理系统模板(图):人人网

网站优化优采云 发表了文章 • 0 个评论 • 86 次浏览 • 2022-09-02 17:02 • 来自相关话题

  cms网站后台内容管理系统模板(图):人人网
  cms网站后台内容管理系统模板了解一下dz:人人网discuz:5655mcshop:?q=%e4%bf%be%e4%b8%88&aq=f&oq=%e4%bf%be%e4%b8%88&aqi=&aql=&aqlp=&by=&biw=1933&bih=2248建议用dz模板,前景还是很不错的;dz压力很小,性能还是挺不错的。其实用模板做建站是很有必要的,手写代码是很耗费精力的,建议用模板解决日常工作需要。
  
  mvc分层架构和springboot比较,关注点不同。
  如果是我的话,我选择用dz,因为这个模板非常好。这里推荐一下网站流量管理系统gweb而且压力也很小。如果是小公司的话我建议用dz(贵),做大了再搞springboot吧。大公司有成熟的开源技术模板也不错,使用的很多,你可以选择一个,什么时候都是拿来主义。
  
  就网站数据库存储来说,现在的网站数据库都可以支持各种标准化模板,这种方案不收学费,重点在于应用维护。一次建站,高维护成本。后期数据同步会成为问题。选择合适的建站工具是第一个挑战。数据库管理是长期的事情,急不得。人肉查询用google或者百度都可以。安全性,性能,维护性,
  wordpress、phpwind、dz都有模板和插件制作功能,可以从模板制作功能和插件制作功能去了解dz和phpwind,可以按目前的各自强项分别重点选择,根据模板制作和插件制作从而选择出最适合你的phpwind和dz,当然这样选择会麻烦一些,可以根据站点大小的接近作一些前期的准备。假如是phpwind和dz都不合适,那么就可以看下针对性内容、性能的phpmyadmin和dw这两款插件,再做做互联网收集的尝试。 查看全部

  cms网站后台内容管理系统模板(图):人人网
  cms网站后台内容管理系统模板了解一下dz:人人网discuz:5655mcshop:?q=%e4%bf%be%e4%b8%88&aq=f&oq=%e4%bf%be%e4%b8%88&aqi=&aql=&aqlp=&by=&biw=1933&bih=2248建议用dz模板,前景还是很不错的;dz压力很小,性能还是挺不错的。其实用模板做建站是很有必要的,手写代码是很耗费精力的,建议用模板解决日常工作需要。
  
  mvc分层架构和springboot比较,关注点不同。
  如果是我的话,我选择用dz,因为这个模板非常好。这里推荐一下网站流量管理系统gweb而且压力也很小。如果是小公司的话我建议用dz(贵),做大了再搞springboot吧。大公司有成熟的开源技术模板也不错,使用的很多,你可以选择一个,什么时候都是拿来主义。
  
  就网站数据库存储来说,现在的网站数据库都可以支持各种标准化模板,这种方案不收学费,重点在于应用维护。一次建站,高维护成本。后期数据同步会成为问题。选择合适的建站工具是第一个挑战。数据库管理是长期的事情,急不得。人肉查询用google或者百度都可以。安全性,性能,维护性,
  wordpress、phpwind、dz都有模板和插件制作功能,可以从模板制作功能和插件制作功能去了解dz和phpwind,可以按目前的各自强项分别重点选择,根据模板制作和插件制作从而选择出最适合你的phpwind和dz,当然这样选择会麻烦一些,可以根据站点大小的接近作一些前期的准备。假如是phpwind和dz都不合适,那么就可以看下针对性内容、性能的phpmyadmin和dw这两款插件,再做做互联网收集的尝试。

cms网站后台内容管理系统模板(图)官方介绍

网站优化优采云 发表了文章 • 0 个评论 • 98 次浏览 • 2022-08-21 22:02 • 来自相关话题

  cms网站后台内容管理系统模板(图)官方介绍
  cms网站后台内容管理系统模板目前总共四个系列,分别是martial型,redux型,grid型以及simulation型的。redux出了问题后,就推荐你一个微信小程序版,网站生成版也有,cms模板市场分别是eclipse,maven之类。使用markdown语法,后端php和nodejs都支持。redux和serviceworker网站服务器只要一台就行,nodejs即可。
  前端每个模板的布局包括图片风格都是我自己开发的。simulation系列基本全部用javascript实现,不一一细说。总之也都是实战中总结的。
  直接从网上搜有没有现成的
  
  最终效果如图
  推荐这个吧linkedin官方的!
  注册完需要进行简单的注册,同时你也需要填写一些基本的信息,然后到注册模板中心提交网站信息。注册模板中心可以选择一个开发者或者个人或者企业等,针对于个人或者企业进行创建,你也可以注册一个谷歌账号到谷歌商店里进行搜索。谷歌商店也是有的,不过不支持中文的版本,不知道网站是不是支持。其他的就不知道了。
  
  你登录网站后台就能找到了
  有微信小程序端,你登录后台就能找到了。
  有个链接,注册了那个账号,
  不知道你有没有注册成功注册成功链接/,貌似at&t这个网站有这个开发者登录的系统,你可以注册at&t的账号, 查看全部

  cms网站后台内容管理系统模板(图)官方介绍
  cms网站后台内容管理系统模板目前总共四个系列,分别是martial型,redux型,grid型以及simulation型的。redux出了问题后,就推荐你一个微信小程序版,网站生成版也有,cms模板市场分别是eclipse,maven之类。使用markdown语法,后端php和nodejs都支持。redux和serviceworker网站服务器只要一台就行,nodejs即可。
  前端每个模板的布局包括图片风格都是我自己开发的。simulation系列基本全部用javascript实现,不一一细说。总之也都是实战中总结的。
  直接从网上搜有没有现成的
  
  最终效果如图
  推荐这个吧linkedin官方的!
  注册完需要进行简单的注册,同时你也需要填写一些基本的信息,然后到注册模板中心提交网站信息。注册模板中心可以选择一个开发者或者个人或者企业等,针对于个人或者企业进行创建,你也可以注册一个谷歌账号到谷歌商店里进行搜索。谷歌商店也是有的,不过不支持中文的版本,不知道网站是不是支持。其他的就不知道了。
  
  你登录网站后台就能找到了
  有微信小程序端,你登录后台就能找到了。
  有个链接,注册了那个账号,
  不知道你有没有注册成功注册成功链接/,貌似at&t这个网站有这个开发者登录的系统,你可以注册at&t的账号,

企业网站的费用和流程一览

网站优化优采云 发表了文章 • 0 个评论 • 104 次浏览 • 2022-08-10 22:52 • 来自相关话题

  企业网站的费用和流程一览
  先说常规网站制作需要用到的东西:
  网站建设收费分三个部分 : 域名、服务器、源码(网站的设计制作)
  域名 :
  65元左右一个.com域名
  服务器 :
  企业展示型网站图片视频少,一般200元到300元左右的虚拟主机即可,如果需要承载大量宣传视频和高清案例图片,价格会贵一些。
  功能型网站,根据承载的业务量来选择服务器,价格从一千多到几千块上万不等。
  源码(网站的设计制作):
  企业/个人展示型网站一般300到500块钱。
  品牌型网站和营销型网站根据设计需要一般1000元起。
  功能型网站根据功能按需定制,价格一般一万起,开发周期正常都是最少三周起。(包含数据测试、压力测试、兼容性测试等等)。
  我们有多年稳定运行的建站软件平台,并且常年维护更新。快速帮助企业或个人完成网站搭建和上线。我们提供数千款精美网站素材和模板,且都是正版可商用,并提供云服务器和域名一键配置。快速帮助您建设制作高端大气商务网站和官方网站。
  
  您的担心:
  网站会不会被百度收录?
  内置一键提交百度收录,快速被百度收录。
  网站优化是不是很难做?
  内置配套SEO功能,只需要按提示设置关键词即可轻松优化整站和单页面搜索排名。即使不懂SEO也能轻松优化网站排名。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询
  随着互联网的发展,很多企业想要建立一个自己的企业网站,但是又苦于不懂技术,不清楚网站建设都有哪些费用和流程。下面跟大家科普一下,网站建设一般有哪些费用?
  企业网站建设一般有哪些费用
  
  一、域名和服务器空间费用
  网站建设时需要先申请域名,域名是什么?干什么用的?其实,域名就相当于你的企业名称,而注册域名最常见的用途就是建网站,因为它可以直接进行网站访问。一个好域名可以使你的网站在推广过程中更加省力,让目标群容易记住。网站的域名是英语顶级域名的首选。com或。cn。一般来说,使用一个域名的成本是每年几十元左右。可以说,这是整个网站建设项目成本最少的一项,几乎可以忽略不计。
  服务器是建站的基础,企业网站建设,因为图片比较少,音视频文件也不多,一般像阿里云企业版的主机都是完全够用的,其次是流量和并发数,如果网站有更多的音视频文件,流量也不低,那就是流量消耗比较大,那么选择无限流量空间,无限流量空间一般是无限并发数。企业站的服务器价格一般一年几百到两千元左右就够用了,如果后期访问流量大了,可以适当增加配置。
  二、网站页面设计价格
  一般网站页面设计价格与你所需要的网站设计的效果和功能有关,一般定制站就需要方案、美工、程序员来完成。投入费用也比较多大概在1万左右。适合大型公司及想长期运营网络营销的公司。如果想要缩小成本,就选仿站。通过修改网站的细节,完成自己的网站设计。如果对页面设计要求不高,也可以模版套用。这属于快餐式的网站设计,模版网站也是可以进行二次开发的。通过对模版的源代码进行修改。模版网站的价格一般在1千左右。
  三、后台程序开发费用
  对于企业网站要求不高的可以使用开源CMS后台管理系统,成本相对比较低,对于一般网站来说,只要没有太多的个性化定制功能需求,开源CMS完全能够满足要求。定制开发的后台功能是根据项目的功能要求来确定的,相对来说成本会高一些,响应式网站建设的功能开发成本与传统网站相差不大,这将增加一些后台定制开发成本。
  四 、后期维护费用
  网站建成后,后期保护是必要的。根据客户和企业的不同需求,分为基础维护和全包维护,因为目前网站后台的内容管理系统程序比较完善。在大多数情况下,企业只需要选择基本满足要求的标准保护,而定全包维护的费用没有标准化,要求是根据工作量确定的。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询 查看全部

  企业网站的费用和流程一览
  先说常规网站制作需要用到的东西:
  网站建设收费分三个部分 : 域名、服务器、源码(网站的设计制作)
  域名 :
  65元左右一个.com域名
  服务器 :
  企业展示型网站图片视频少,一般200元到300元左右的虚拟主机即可,如果需要承载大量宣传视频和高清案例图片,价格会贵一些。
  功能型网站,根据承载的业务量来选择服务器,价格从一千多到几千块上万不等。
  源码(网站的设计制作):
  企业/个人展示型网站一般300到500块钱。
  品牌型网站和营销型网站根据设计需要一般1000元起。
  功能型网站根据功能按需定制,价格一般一万起,开发周期正常都是最少三周起。(包含数据测试、压力测试、兼容性测试等等)。
  我们有多年稳定运行的建站软件平台,并且常年维护更新。快速帮助企业或个人完成网站搭建和上线。我们提供数千款精美网站素材和模板,且都是正版可商用,并提供云服务器和域名一键配置。快速帮助您建设制作高端大气商务网站和官方网站。
  
  您的担心:
  网站会不会被百度收录?
  内置一键提交百度收录,快速被百度收录。
  网站优化是不是很难做?
  内置配套SEO功能,只需要按提示设置关键词即可轻松优化整站和单页面搜索排名。即使不懂SEO也能轻松优化网站排名。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询
  随着互联网的发展,很多企业想要建立一个自己的企业网站,但是又苦于不懂技术,不清楚网站建设都有哪些费用和流程。下面跟大家科普一下,网站建设一般有哪些费用?
  企业网站建设一般有哪些费用
  
  一、域名和服务器空间费用
  网站建设时需要先申请域名,域名是什么?干什么用的?其实,域名就相当于你的企业名称,而注册域名最常见的用途就是建网站,因为它可以直接进行网站访问。一个好域名可以使你的网站在推广过程中更加省力,让目标群容易记住。网站的域名是英语顶级域名的首选。com或。cn。一般来说,使用一个域名的成本是每年几十元左右。可以说,这是整个网站建设项目成本最少的一项,几乎可以忽略不计。
  服务器是建站的基础,企业网站建设,因为图片比较少,音视频文件也不多,一般像阿里云企业版的主机都是完全够用的,其次是流量和并发数,如果网站有更多的音视频文件,流量也不低,那就是流量消耗比较大,那么选择无限流量空间,无限流量空间一般是无限并发数。企业站的服务器价格一般一年几百到两千元左右就够用了,如果后期访问流量大了,可以适当增加配置。
  二、网站页面设计价格
  一般网站页面设计价格与你所需要的网站设计的效果和功能有关,一般定制站就需要方案、美工、程序员来完成。投入费用也比较多大概在1万左右。适合大型公司及想长期运营网络营销的公司。如果想要缩小成本,就选仿站。通过修改网站的细节,完成自己的网站设计。如果对页面设计要求不高,也可以模版套用。这属于快餐式的网站设计,模版网站也是可以进行二次开发的。通过对模版的源代码进行修改。模版网站的价格一般在1千左右。
  三、后台程序开发费用
  对于企业网站要求不高的可以使用开源CMS后台管理系统,成本相对比较低,对于一般网站来说,只要没有太多的个性化定制功能需求,开源CMS完全能够满足要求。定制开发的后台功能是根据项目的功能要求来确定的,相对来说成本会高一些,响应式网站建设的功能开发成本与传统网站相差不大,这将增加一些后台定制开发成本。
  四 、后期维护费用
  网站建成后,后期保护是必要的。根据客户和企业的不同需求,分为基础维护和全包维护,因为目前网站后台的内容管理系统程序比较完善。在大多数情况下,企业只需要选择基本满足要求的标准保护,而定全包维护的费用没有标准化,要求是根据工作量确定的。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询

渗透技巧 | 网站后台常见的Getshell技术整理

网站优化优采云 发表了文章 • 0 个评论 • 99 次浏览 • 2022-07-20 23:46 • 来自相关话题

  渗透技巧 | 网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  
  2.网站配置
  复现:
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
  @学习更多渗透技能!体验靶场实战练习
  <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;letter-spacing: 0.544px;">(hack视频资料及工具)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /></p>
  (部分展示)
  往期推荐
  看到这里了,点个“赞”、“再看” 查看全部

  渗透技巧 | 网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  
  2.网站配置
  复现:
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
  @学习更多渗透技能!体验靶场实战练习
  <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;letter-spacing: 0.544px;">(hack视频资料及工具)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /></p>
  (部分展示)
  往期推荐
  看到这里了,点个“赞”、“再看”

文库|网站后台常见的Getshell技术整理

网站优化优采云 发表了文章 • 0 个评论 • 74 次浏览 • 2022-07-16 08:32 • 来自相关话题

  文库|网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  2.网站配置
  复现:
  
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.
  回顾往期内容
  扫码白嫖视频+工具+进群+靶场等资料
  扫码白嫖!
  还有免费的配套靶场、交流群哦 查看全部

  文库|网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  2.网站配置
  复现:
  
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.
  回顾往期内容
  扫码白嫖视频+工具+进群+靶场等资料
  扫码白嫖!
  还有免费的配套靶场、交流群哦

【网站搭建】-网站建设终极版本:13个教学+费用

网站优化优采云 发表了文章 • 0 个评论 • 80 次浏览 • 2022-06-26 18:48 • 来自相关话题

  【网站搭建】-网站建设终极版本:13个教学+费用
  也可以安装免费的Let's Encrypt()证书,还有其它免费安全证书可供选择,差别不大。
  主机
  05
  创建网站,除了需要一个网域,你还需要主机(又称Web hosting、网站空间、服务器)来存放网站上面内容和资料。
  Web hosting有很多种,例如独立服务器,云服务器(云主机),共享型VPS,虚拟主机,关于这几者的比较,可以参考以下我之前的总结:
  从价格来说:
  独立服务器>云服务器>VPS>虚拟主机
  从用户的维护成本来说:
  虚拟主机 从对用户的技术要求来说:
  虚拟主机
  ● 解析域名与绑定域名●
  什么是域名解析
  06
  所有的主机都是有IP地址(比如:110.110.110.110)的,但是这些IP地址太难记了,所以就出现了域名,域名解析就是将域名转换为IP地址的这样一种行为。
  DNS是什么
  07
  DNS(即域名系统,Domain Name System)控制域名的网站和电子邮件设置。当访问者转到你的域名时,其 DNS 设置将域名指向具体的网站服务器,让访客通过这个域名可以访问服务器上的网站。
  以具体例子来说人话:
  IP地址是标准门牌号,域名是昵称俗称。
  比如浦发大厦这个通俗易懂的名字就是域名。
  上海市浦东南路588号这个容易忘记的真实地址就是IP。
  DNS设置就是帮助你通过昵称俗称找到网站真实IP地址的服务。
  它如同网路世界的地址簿,把域名转换成IP -我们只须在浏览器输入域名,就能造访喜欢的网站。DNS是浏览器的指路人。
  设定DNS指向—域名解析
  08
  除了申请路标(域名),你还需要租个房子或者床位(主机/服务器)来装修成卧床(网站)。
  但你得先确认,这个路标(域名)是需要指向你租来的那个房子(主机),这就是DNS指向设定,其实也叫域名解析。
  注:很少人买得起一栋楼(独立服务器)或一层楼(云主机)。绝大多数人或企业,都是租用一个单间(共享性VPS)或者床位(虚拟主机)。
  我们来看实际操作(以Namecheap为例)...
  第一, 登入Namecheap帐户> Domain List > MANAGE >Domain:
  第二, 在NAMESERVERS栏位:
  选择Custom DNS
  贴入主机商提供的DNS位址(这个在购买的主机服务器了会提供)
  储存
  不同服务商的后台会有差异,但操作流程是一样的。
  如果不知道该怎么样用DNS指向设定,还可以用另外一种方法将域名指向主机。
  第一, 登入Namecheap帐户> Domain List > MANAGE >Advanced DNS:
  第二, 在HOST RECORDS栏位,按照如下进行设定:
  绑定域名
  09
  域名绑定实际上就是主机空间上设置权限可以让你的网站域名访问进入的设置。
  下面是流程:
  1 、登录空间商后台,进入主机管理
  2、找到你购买的主机类型,选择管理
  3、进入管理界面后,选择绑定域名
  4、在输入新域名的方框里面输入你的域名,点击增加即可
  具体过程之前在里讲的很详细,具体不再叙述。
  ●如何建设网站●
  网站建设流程有四:
  1.注册域名(申请一个路标)
  2.设定DNS指向(把路标指向你租来的那间房子)
  3.租用虚拟主机(租一间房子)
  4.安装建站程序(来装饰房子)
  根据前面的教学,你已学会第一项、第二项。
  以下,我将教你第三、四项。
  准备好了吗?开始吧!
  虚拟主机推荐
  10
  如何比较主机商?除了价格、规模、评价与24小时客服之外,你还要考虑它的机房位置。
  若你的目标访客都在大陆,虚拟主机机房最好在大陆,或邻近的亚洲国家或地区- 如新加坡、日本、香港、台湾。
  机房在地球的另一端会产生网路延迟,进而影响使用者经验。若网站是你赖以为生的工具,你当然要提供最好的“用户体验”,不是吗?
  商务网站主机我推荐SiteGround
  优点:
  价格公道(每月最低$3.95美元)
  免费SSL证书
  CDN免费加速服务
  全年无休、24小时客服
  
  Siteground真码实价
  免费的网站备份
  免费的网站迁移服务
  30天退款保证
  缺点:
  人工客服很鸡贼,常常找不到人工客服的通道。
  关于SiteGround的教学下次出一篇文章专门介绍,如果想购买的话,可以通过以下通道直达:
  博客网站主机我推荐GoDaddy 1美元主机
  关于这个1美元主机,我之前写过(点击以上链接看我以前的这篇文章),可以通过此链接直达1美元主机购买通道,否则在GoDaddy主页上购买的这个机型就不止这个价格了。
  免费主机我推荐谷歌云主机
  谷歌云主机是性能相当好的主机,而且由于在你申请谷歌云主机时,都会给你300美金试用金,相当于你使用这个主机就是免费的。
  如何申请到谷歌云的这300美金,我之前写过,最近经小伙伴反馈,这些方法部分失效,总结如下:
  P卡还能否作为申请的付款账号?
  这真得看命,亲测部分人可以,部分人被拒绝了。
  XX单标信用卡还能否申请?
  说实话,能否申请,我只能告诉你以前单标卡都是可以申请,但最近被和谐了,具体哪些单标卡没有被和谐,我也不清楚。自己手中的单标卡能否申请,try it即可,我不负责帮你回答哪些银行卡可用。
  XX信用卡为什么不能申请?
  我之前回答过,当雪崩时,没有一片雪花是无辜的,这300美金被太多人薅了,Google只好出动终极手段,双币信用卡早就被排除在可用范围之内,近期单标信用卡(就是只能使用外币的信用卡)也被踢出了局。
  还有没有申请这300美金的办法?
  有,找一个有外国信用卡的朋友帮你忙,过一段时间我再推出新的办法。
  网页建设的程序
  11
  自制网站的方式有三种:
  1. 用HTML、CSS、JavaScript... 语言,自己开发网页
  2. 使用自助建站平台,如SHOPLINE、SHOPIFY、WIX
  3. 使用CMS(Content Management System,内容管理系统)建站系统,如WordPress、Joomla!、Drupal
  若你非程序员,我建议你不要考虑第一项。
  “建站平台”是最轻松、快速之架站方式,这边,我们先讨论CMS...,关于自助建站平台Shopify与CMS WordPress以及其它的比较,我写过相关方面的。
  全球有约一半的网站,使用CMS,而全球有超过30%的网站,使用WordPress。也就是说,WordPress在CMS的市占率,超过60%。
  ● 关于WordPress程序●
  WordPress是什么
  12
  WordPress是一个内容管理系统。它有设计完善的后台,让你管理网站上所有内容,例如文章、页面、多媒体。
  WordPress的主要目的,一开始是用着建设一个博客网站,发表文章和多媒体。若你需要其他功能,如CRM、开发票...则你应该使用专门程序,而不是WordPress。
  你可以安装WordPress插件来扩充功能,WordPress有上千个插件---有免费的,也有付费的。
  如果你想把网站变成一个电子商务网站,就可以安装WooCommerce插件。
  WordPress主题(又称版型)决定网站的外观。如同插件,WordPress主题有免费、也有付费的。如前述,全球有近30%的网站是WordPress。因此市场上充满各式各样的主题及插件。
  ●WordPress教学●
  如何建设网站
  13
  在前面的URL是什么,我提到所谓“网站”,其实是由文件和数据包组成。
  一般的虚拟主机建设网站,经常要用File Manager或FTP软件,来管理这些文件和数据包,而建站平台帮你免除这些烦恼,比如电商平台的建站平台Shopify,如果你没有任何技术基础,你可以利用Shopify快速搭建一个电商网站,因为有了Shopify,你不用懂什么是服务器,SSL,FTP,CPanel,这些东西都有Shopify后台技术帮你打理,你利用主题模板就可以搭建一款与模板类似网站。
  但是如果你懂一点建站技术,我就推荐你利用WordPress+WooCommerce搭建电商网站,因为它更实惠。
  关于是用Shopify还是用WooCommerce搭建网站,请参考我的这篇文章:
  在我看来,用WordPress+WooCommerce搭建电商网站也不是太难的事,按照我这篇文章流程走下来,基本上就把一个电商网站的基础框架搭建起来。
  制作WordPress网页的流程有:
  1. 登入后台
  2.设定/更改网址结构
  3.安装WordPress主题
  4.自订外观
  5.安装插件
  6.管理留言板
  7.注册Gravatar大头贴
  8.备份WordPress网站(一键打包)
  9.角色权限管理
  10.增加影音媒体
  11.发表文章 查看全部

  【网站搭建】-网站建设终极版本:13个教学+费用
  也可以安装免费的Let's Encrypt()证书,还有其它免费安全证书可供选择,差别不大。
  主机
  05
  创建网站,除了需要一个网域,你还需要主机(又称Web hosting、网站空间、服务器)来存放网站上面内容和资料。
  Web hosting有很多种,例如独立服务器,云服务器(云主机),共享型VPS,虚拟主机,关于这几者的比较,可以参考以下我之前的总结:
  从价格来说:
  独立服务器>云服务器>VPS>虚拟主机
  从用户的维护成本来说:
  虚拟主机 从对用户的技术要求来说:
  虚拟主机
  ● 解析域名与绑定域名●
  什么是域名解析
  06
  所有的主机都是有IP地址(比如:110.110.110.110)的,但是这些IP地址太难记了,所以就出现了域名,域名解析就是将域名转换为IP地址的这样一种行为。
  DNS是什么
  07
  DNS(即域名系统,Domain Name System)控制域名的网站和电子邮件设置。当访问者转到你的域名时,其 DNS 设置将域名指向具体的网站服务器,让访客通过这个域名可以访问服务器上的网站。
  以具体例子来说人话:
  IP地址是标准门牌号,域名是昵称俗称。
  比如浦发大厦这个通俗易懂的名字就是域名。
  上海市浦东南路588号这个容易忘记的真实地址就是IP。
  DNS设置就是帮助你通过昵称俗称找到网站真实IP地址的服务。
  它如同网路世界的地址簿,把域名转换成IP -我们只须在浏览器输入域名,就能造访喜欢的网站。DNS是浏览器的指路人。
  设定DNS指向—域名解析
  08
  除了申请路标(域名),你还需要租个房子或者床位(主机/服务器)来装修成卧床(网站)。
  但你得先确认,这个路标(域名)是需要指向你租来的那个房子(主机),这就是DNS指向设定,其实也叫域名解析。
  注:很少人买得起一栋楼(独立服务器)或一层楼(云主机)。绝大多数人或企业,都是租用一个单间(共享性VPS)或者床位(虚拟主机)。
  我们来看实际操作(以Namecheap为例)...
  第一, 登入Namecheap帐户> Domain List > MANAGE >Domain:
  第二, 在NAMESERVERS栏位:
  选择Custom DNS
  贴入主机商提供的DNS位址(这个在购买的主机服务器了会提供)
  储存
  不同服务商的后台会有差异,但操作流程是一样的。
  如果不知道该怎么样用DNS指向设定,还可以用另外一种方法将域名指向主机。
  第一, 登入Namecheap帐户> Domain List > MANAGE >Advanced DNS:
  第二, 在HOST RECORDS栏位,按照如下进行设定:
  绑定域名
  09
  域名绑定实际上就是主机空间上设置权限可以让你的网站域名访问进入的设置。
  下面是流程:
  1 、登录空间商后台,进入主机管理
  2、找到你购买的主机类型,选择管理
  3、进入管理界面后,选择绑定域名
  4、在输入新域名的方框里面输入你的域名,点击增加即可
  具体过程之前在里讲的很详细,具体不再叙述。
  ●如何建设网站●
  网站建设流程有四:
  1.注册域名(申请一个路标)
  2.设定DNS指向(把路标指向你租来的那间房子)
  3.租用虚拟主机(租一间房子)
  4.安装建站程序(来装饰房子)
  根据前面的教学,你已学会第一项、第二项。
  以下,我将教你第三、四项。
  准备好了吗?开始吧!
  虚拟主机推荐
  10
  如何比较主机商?除了价格、规模、评价与24小时客服之外,你还要考虑它的机房位置。
  若你的目标访客都在大陆,虚拟主机机房最好在大陆,或邻近的亚洲国家或地区- 如新加坡、日本、香港、台湾。
  机房在地球的另一端会产生网路延迟,进而影响使用者经验。若网站是你赖以为生的工具,你当然要提供最好的“用户体验”,不是吗?
  商务网站主机我推荐SiteGround
  优点:
  价格公道(每月最低$3.95美元)
  免费SSL证书
  CDN免费加速服务
  全年无休、24小时客服
  
  Siteground真码实价
  免费的网站备份
  免费的网站迁移服务
  30天退款保证
  缺点:
  人工客服很鸡贼,常常找不到人工客服的通道。
  关于SiteGround的教学下次出一篇文章专门介绍,如果想购买的话,可以通过以下通道直达:
  博客网站主机我推荐GoDaddy 1美元主机
  关于这个1美元主机,我之前写过(点击以上链接看我以前的这篇文章),可以通过此链接直达1美元主机购买通道,否则在GoDaddy主页上购买的这个机型就不止这个价格了。
  免费主机我推荐谷歌云主机
  谷歌云主机是性能相当好的主机,而且由于在你申请谷歌云主机时,都会给你300美金试用金,相当于你使用这个主机就是免费的。
  如何申请到谷歌云的这300美金,我之前写过,最近经小伙伴反馈,这些方法部分失效,总结如下:
  P卡还能否作为申请的付款账号?
  这真得看命,亲测部分人可以,部分人被拒绝了。
  XX单标信用卡还能否申请?
  说实话,能否申请,我只能告诉你以前单标卡都是可以申请,但最近被和谐了,具体哪些单标卡没有被和谐,我也不清楚。自己手中的单标卡能否申请,try it即可,我不负责帮你回答哪些银行卡可用。
  XX信用卡为什么不能申请?
  我之前回答过,当雪崩时,没有一片雪花是无辜的,这300美金被太多人薅了,Google只好出动终极手段,双币信用卡早就被排除在可用范围之内,近期单标信用卡(就是只能使用外币的信用卡)也被踢出了局。
  还有没有申请这300美金的办法?
  有,找一个有外国信用卡的朋友帮你忙,过一段时间我再推出新的办法。
  网页建设的程序
  11
  自制网站的方式有三种:
  1. 用HTML、CSS、JavaScript... 语言,自己开发网页
  2. 使用自助建站平台,如SHOPLINE、SHOPIFY、WIX
  3. 使用CMS(Content Management System,内容管理系统)建站系统,如WordPress、Joomla!、Drupal
  若你非程序员,我建议你不要考虑第一项。
  “建站平台”是最轻松、快速之架站方式,这边,我们先讨论CMS...,关于自助建站平台Shopify与CMS WordPress以及其它的比较,我写过相关方面的。
  全球有约一半的网站,使用CMS,而全球有超过30%的网站,使用WordPress。也就是说,WordPress在CMS的市占率,超过60%。
  ● 关于WordPress程序●
  WordPress是什么
  12
  WordPress是一个内容管理系统。它有设计完善的后台,让你管理网站上所有内容,例如文章、页面、多媒体。
  WordPress的主要目的,一开始是用着建设一个博客网站,发表文章和多媒体。若你需要其他功能,如CRM、开发票...则你应该使用专门程序,而不是WordPress。
  你可以安装WordPress插件来扩充功能,WordPress有上千个插件---有免费的,也有付费的。
  如果你想把网站变成一个电子商务网站,就可以安装WooCommerce插件。
  WordPress主题(又称版型)决定网站的外观。如同插件,WordPress主题有免费、也有付费的。如前述,全球有近30%的网站是WordPress。因此市场上充满各式各样的主题及插件。
  ●WordPress教学●
  如何建设网站
  13
  在前面的URL是什么,我提到所谓“网站”,其实是由文件和数据包组成。
  一般的虚拟主机建设网站,经常要用File Manager或FTP软件,来管理这些文件和数据包,而建站平台帮你免除这些烦恼,比如电商平台的建站平台Shopify,如果你没有任何技术基础,你可以利用Shopify快速搭建一个电商网站,因为有了Shopify,你不用懂什么是服务器,SSL,FTP,CPanel,这些东西都有Shopify后台技术帮你打理,你利用主题模板就可以搭建一款与模板类似网站。
  但是如果你懂一点建站技术,我就推荐你利用WordPress+WooCommerce搭建电商网站,因为它更实惠。
  关于是用Shopify还是用WooCommerce搭建网站,请参考我的这篇文章:
  在我看来,用WordPress+WooCommerce搭建电商网站也不是太难的事,按照我这篇文章流程走下来,基本上就把一个电商网站的基础框架搭建起来。
  制作WordPress网页的流程有:
  1. 登入后台
  2.设定/更改网址结构
  3.安装WordPress主题
  4.自订外观
  5.安装插件
  6.管理留言板
  7.注册Gravatar大头贴
  8.备份WordPress网站(一键打包)
  9.角色权限管理
  10.增加影音媒体
  11.发表文章

【网站模板】第01期—15套免费网站后台管理模板

网站优化优采云 发表了文章 • 0 个评论 • 76 次浏览 • 2022-06-21 13:41 • 来自相关话题

  【网站模板】第01期—15套免费网站后台管理模板
  
  作者 | web小二
  来源 | web前端开发公众号(ID:web_qdkf)
  很早之前,我跟大家分享过一期关于网站后台管理的文章《》在这篇文章中,我跟大家讲了,我之前因为在企业做可视项目的时候,找了很多案例进行参考,但是一直没有把它们全部整理处理进行分享,上次只是精选了一些我认为比较好的模板案例分享给大家。这一次,我想把这个源码模板案例作为一个长期的免费学习资料分享给大家,希望对大家学习有帮助。
  后面每期内容大概会分享10-15款网站源码模板,这些网站模板都是我通过网络收集整理而成,希望对大家有所帮助。下面就开始今天的第一期内容。
  01、订单销售统计电商后台系统
  这是一款使用Bootstrap构建的电商后台管理系统页面模板。里面包含订单销售、商品管理、销售营业额统计后台管理页面;还有多个ui组件,图表库、日历、文本表单、日期范围、上传区域,形成自动完成,滑块范围,进度条、通知消息等。下载地址: 访问密码:269802、电商业务数据统计后台模板
  这一款后台管理模板是基于vue实现的电商app,电商订单,电商销售数据统计后台管理系统模板。适合电子商务商城网站admin系统。界面使用tab选项卡的方式,无刷新效果很好。这套后台模板是github项目,请参考帮助文档。ps:如果不懂vue,也没有编程基础的话,不建议直接学习。下载地址: 访问密码:269803、H5物流大数据展示后台投票模板
  
  这一款科技感十足的物流大数据系统,物流数据概况系统,物流订单系统,物流信息系统后台多个展示大屏模板。ps:本地需在localhost下进行访问。下载地址: 访问密码:269804、App商城销售后台统计页面模板
  这一款是基于bootstrap构建,中文版的商品销售统计管理,商城订单销售,商城累计收入统计后台管理UI框架模板。包含完整的UI元素页面,是个通用的前端后台框架模板。下载地址: 访问密码:269805、课程教育系统管理后台模板
  
  这款是基于bootstrap框架和jquery插件,多用途的教育行业以及网络课程系统管理,是一套教育平台网站后台页面模板。这套管理后台模板用途很广泛,适用于教育管理软件,很容易修改定制。下载地址: 访问密码:269806、电商业务销售管理系统模板
  
  这款是基于bootstrap框架构建的蓝色多用途电商产品业务销售管理系统,里面有每月营业额统计管理UI框架模板。下载地址: 访问密码:269807、医院就诊统计管理模板
  
  这一款多用途的医院医生就诊统计,医疗服务统计管理后台HTML模板。适用于:医院、医疗行业管理系统,当然,你也可以使用这套模板创建任何类型的管理软件,或者网站后台、数据统计分析等。下载地址: 访问密码:269808、电商业务销售统计后台界面模板
  
  这款模板是基于bootstrap前端框架构建的,电商销售统计/公司业绩销售管理后台模板。适用于任何类型的电商网站后台,管理应用软件web前端模板等。下载地址: 访问密码:269809、广告流量分析统计管理后台模板
  这款也是基于Bootstrap构建的,黑色的app后台流量统计,访客数量统计,广告自媒体流量统计管理后台ui框架模板。使用了最新jQuery UI组件和Bootstrap插件。适用于任何的web应用程序电子商务仪表板,定制管理面板,crm、cms项目管理管理等。下载地址: 访问密码:269810、产品订单销售电商后台模板
  这是一款基于Bootstrap构建,产品订单管理/产品销售/电商后台系统模板。模板附带很多小部件和组件。它有一个巨大的可重用的UI组件集成模板。下载地址: 访问密码:269811、云文件存储管理后台模板
  
  这个是一款多功能的云端图片文件管理,云共享,云储存后台管理系统模板。它由用户管理模块、auth模块、ui页面、表单页面等响应式后台页面布局。下载地址: 访问密码:2698
  12、响应式app业务数据统计后台模板
  
  这款模板基于bootstrap框架,jQuery构建,响应式的app数据统计管理后台模板。包含很多UI元素、组件、web应用程序、数据仪表板、CRM、CMS、电子商务面板页面等。它有很多可以使用页面,如身份验证、电子邮件、日历、错误、faq、博客文章、搜索、用户配置文件等。
  下载地址: 访问密码:2698
  13、健身App管理后台模板
  
  这款模板基于Bootstrap构建,响应式的运动健身App统计管理,健身项目管理,私人健身服务后台管理模板。下载地址: 访问密码:269814、餐饮业务管理系统后台模板
  这款模板是基于html5与 Bootstrap构建的,可以在餐饮行业进行使用,餐饮电商系统,餐饮外卖订单,餐饮业务销售管理响应式后台模板。
  下载地址: 访问密码:269815、企业网站后台管理页面模板
  这款后面模板是基于Bootstrap构建,轻量级的BsAdmin企业网站后台模板,风格简洁简单,是中小型项目首选,不管你是初级还是高级工程师,都有可以快速上手。BsAdmin是由Bootstrap4开发,可以在模板任意使用jq或vue。下载地址: 访问密码:2698
  本文完〜
   查看全部

  【网站模板】第01期—15套免费网站后台管理模板
  
  作者 | web小二
  来源 | web前端开发公众号(ID:web_qdkf)
  很早之前,我跟大家分享过一期关于网站后台管理的文章《》在这篇文章中,我跟大家讲了,我之前因为在企业做可视项目的时候,找了很多案例进行参考,但是一直没有把它们全部整理处理进行分享,上次只是精选了一些我认为比较好的模板案例分享给大家。这一次,我想把这个源码模板案例作为一个长期的免费学习资料分享给大家,希望对大家学习有帮助。
  后面每期内容大概会分享10-15款网站源码模板,这些网站模板都是我通过网络收集整理而成,希望对大家有所帮助。下面就开始今天的第一期内容。
  01、订单销售统计电商后台系统
  这是一款使用Bootstrap构建的电商后台管理系统页面模板。里面包含订单销售、商品管理、销售营业额统计后台管理页面;还有多个ui组件,图表库、日历、文本表单、日期范围、上传区域,形成自动完成,滑块范围,进度条、通知消息等。下载地址: 访问密码:269802、电商业务数据统计后台模板
  这一款后台管理模板是基于vue实现的电商app,电商订单,电商销售数据统计后台管理系统模板。适合电子商务商城网站admin系统。界面使用tab选项卡的方式,无刷新效果很好。这套后台模板是github项目,请参考帮助文档。ps:如果不懂vue,也没有编程基础的话,不建议直接学习。下载地址: 访问密码:269803、H5物流大数据展示后台投票模板
  
  这一款科技感十足的物流大数据系统,物流数据概况系统,物流订单系统,物流信息系统后台多个展示大屏模板。ps:本地需在localhost下进行访问。下载地址: 访问密码:269804、App商城销售后台统计页面模板
  这一款是基于bootstrap构建,中文版的商品销售统计管理,商城订单销售,商城累计收入统计后台管理UI框架模板。包含完整的UI元素页面,是个通用的前端后台框架模板。下载地址: 访问密码:269805、课程教育系统管理后台模板
  
  这款是基于bootstrap框架和jquery插件,多用途的教育行业以及网络课程系统管理,是一套教育平台网站后台页面模板。这套管理后台模板用途很广泛,适用于教育管理软件,很容易修改定制。下载地址: 访问密码:269806、电商业务销售管理系统模板
  
  这款是基于bootstrap框架构建的蓝色多用途电商产品业务销售管理系统,里面有每月营业额统计管理UI框架模板。下载地址: 访问密码:269807、医院就诊统计管理模板
  
  这一款多用途的医院医生就诊统计,医疗服务统计管理后台HTML模板。适用于:医院、医疗行业管理系统,当然,你也可以使用这套模板创建任何类型的管理软件,或者网站后台、数据统计分析等。下载地址: 访问密码:269808、电商业务销售统计后台界面模板
  
  这款模板是基于bootstrap前端框架构建的,电商销售统计/公司业绩销售管理后台模板。适用于任何类型的电商网站后台,管理应用软件web前端模板等。下载地址: 访问密码:269809、广告流量分析统计管理后台模板
  这款也是基于Bootstrap构建的,黑色的app后台流量统计,访客数量统计,广告自媒体流量统计管理后台ui框架模板。使用了最新jQuery UI组件和Bootstrap插件。适用于任何的web应用程序电子商务仪表板,定制管理面板,crm、cms项目管理管理等。下载地址: 访问密码:269810、产品订单销售电商后台模板
  这是一款基于Bootstrap构建,产品订单管理/产品销售/电商后台系统模板。模板附带很多小部件和组件。它有一个巨大的可重用的UI组件集成模板。下载地址: 访问密码:269811、云文件存储管理后台模板
  
  这个是一款多功能的云端图片文件管理,云共享,云储存后台管理系统模板。它由用户管理模块、auth模块、ui页面、表单页面等响应式后台页面布局。下载地址: 访问密码:2698
  12、响应式app业务数据统计后台模板
  
  这款模板基于bootstrap框架,jQuery构建,响应式的app数据统计管理后台模板。包含很多UI元素、组件、web应用程序、数据仪表板、CRM、CMS、电子商务面板页面等。它有很多可以使用页面,如身份验证、电子邮件、日历、错误、faq、博客文章、搜索、用户配置文件等。
  下载地址: 访问密码:2698
  13、健身App管理后台模板
  
  这款模板基于Bootstrap构建,响应式的运动健身App统计管理,健身项目管理,私人健身服务后台管理模板。下载地址: 访问密码:269814、餐饮业务管理系统后台模板
  这款模板是基于html5与 Bootstrap构建的,可以在餐饮行业进行使用,餐饮电商系统,餐饮外卖订单,餐饮业务销售管理响应式后台模板。
  下载地址: 访问密码:269815、企业网站后台管理页面模板
  这款后面模板是基于Bootstrap构建,轻量级的BsAdmin企业网站后台模板,风格简洁简单,是中小型项目首选,不管你是初级还是高级工程师,都有可以快速上手。BsAdmin是由Bootstrap4开发,可以在模板任意使用jq或vue。下载地址: 访问密码:2698
  本文完〜
  

用这些后台管理模版后,三天完成项目!

网站优化优采云 发表了文章 • 0 个评论 • 92 次浏览 • 2022-06-20 14:40 • 来自相关话题

  用这些后台管理模版后,三天完成项目!
  前言
  你是否遇到过PM今天丢给你一堆后台管理系统的需求文档,并说这个产品下个星期上线没有问题吧!
  
  然后你是不是就已经做好了007奋战项目的准备了,其实大可不必,我们首先需要做的是技术选型,然后基于这个框架去完成需求,因为框架的加持可以给我们带来很多的开发便利,提高写代码的效率。
  这里找了几款Vue的后台管理模版,希望给同样被PM安排写需求的你代码写起来能够"策马奔腾"。
  Vue Element Admin
  github获得⭐ 70.2k
  github地址:
  vue-element-admin 是一个后台管理系统案例,它基于 vue 和 element-ui实现,使用最新的前端技术栈,内置了 i18n 国际化解决方案。动态路由、权限验证、提炼了典型的业务模型,提供了丰富的*功能组件,可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
  
  vue2-manage
  github获得⭐ 11.0k
  github地址:
  vue2-manage 是一个前端后端系统、手机端系统的案例,它是基于 vue2 + vuex + vue-router + webpack + ES6/7 + less + element-ui 完成的,后端则采用 nodejs + express + mongodb + mongoose 的架构,客户端采用基于 Flutter 构建的兼容IOS和Android的原生APP.可以说是比较完整的一个前端、后端、用户端都包含的餐饮行业的完整项目了。有兴趣自己搭建完整项目练手的小伙伴可以参考参考。
  PC管理后台:
  APP客户端:
  
  非常适合遇到做电商项目的基础搭建架构。
  
  妈妈再也不用担心我不会做电商系统了。
  vue-manage-system
  github获得⭐ 13.5k
  github地址:
  vue-manage-system 是一个 Vue3 + Element Plus 的后台管理系统解决方案。使用 vue-cli3 脚手架,引用 Element Plus 组件库,方便开发快速简洁好看的组件。支持手动切换主题色,而且很方便使用自定义主题色,并且使用含有富文本的案例。
  
  mall-admin-web
  github获得⭐ 8.7k
  github地址:
  mall-admin-web 是一个 电商后台管理系统 的前端项目,基于 Vue+Element 实现。主要包括 商品管理、订单管理 、会员管理 、促销管理 、运营管理 、内容管理 、统计报表 、财务管理 、权限管理 、设置等功能。对于电商后台管理系统来说非常全面了。
  技术选型:
  预览界面:
  
  角色分配也相当明确:
  
  当然它也配备了手机端的项目:
  
  
  都是非常不错的案例,对应的后台代码也有发布出来。后端代码基于 SpringBoot+MyBatis 实现,采用 Docker 容器化部署。有兴趣的小伙伴自行翻阅。
  RuoYi-Vue
  gitee获得⭐ 11.3k
  gitee地址:
  若依是一个开源项目,用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手。
  它有自己的开发文档介绍和使用手册。
  
  
  jeecg-boot
  github获得⭐ 24.6k
  github地址:
  jeecg-boot 号称是一款基于 代码生成器 的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发!
  它可以应用在任何J2EE项目的开发中,尤其适合SAAS项目、企业信息管理系统(MIS)、内部办公系统(OA)、企业资源计划系统(ERP)、客户关系管理系统(CRM)等,其半智能手工Merge的开发方式,可以显著提高开发效率70%以上,极大降低开发成本。
  
  
  内容太多,就不一一截图展示了,有兴趣的小伙伴自行查阅参考吧。另外,这里的数据库设计也相当巧妙!后端的大佬可以参考下。 查看全部

  用这些后台管理模版后,三天完成项目!
  前言
  你是否遇到过PM今天丢给你一堆后台管理系统的需求文档,并说这个产品下个星期上线没有问题吧!
  
  然后你是不是就已经做好了007奋战项目的准备了,其实大可不必,我们首先需要做的是技术选型,然后基于这个框架去完成需求,因为框架的加持可以给我们带来很多的开发便利,提高写代码的效率。
  这里找了几款Vue的后台管理模版,希望给同样被PM安排写需求的你代码写起来能够"策马奔腾"。
  Vue Element Admin
  github获得⭐ 70.2k
  github地址:
  vue-element-admin 是一个后台管理系统案例,它基于 vue 和 element-ui实现,使用最新的前端技术栈,内置了 i18n 国际化解决方案。动态路由、权限验证、提炼了典型的业务模型,提供了丰富的*功能组件,可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
  
  vue2-manage
  github获得⭐ 11.0k
  github地址:
  vue2-manage 是一个前端后端系统、手机端系统的案例,它是基于 vue2 + vuex + vue-router + webpack + ES6/7 + less + element-ui 完成的,后端则采用 nodejs + express + mongodb + mongoose 的架构,客户端采用基于 Flutter 构建的兼容IOS和Android的原生APP.可以说是比较完整的一个前端、后端、用户端都包含的餐饮行业的完整项目了。有兴趣自己搭建完整项目练手的小伙伴可以参考参考。
  PC管理后台:
  APP客户端:
  
  非常适合遇到做电商项目的基础搭建架构。
  
  妈妈再也不用担心我不会做电商系统了。
  vue-manage-system
  github获得⭐ 13.5k
  github地址:
  vue-manage-system 是一个 Vue3 + Element Plus 的后台管理系统解决方案。使用 vue-cli3 脚手架,引用 Element Plus 组件库,方便开发快速简洁好看的组件。支持手动切换主题色,而且很方便使用自定义主题色,并且使用含有富文本的案例。
  
  mall-admin-web
  github获得⭐ 8.7k
  github地址:
  mall-admin-web 是一个 电商后台管理系统 的前端项目,基于 Vue+Element 实现。主要包括 商品管理、订单管理 、会员管理 、促销管理 、运营管理 、内容管理 、统计报表 、财务管理 、权限管理 、设置等功能。对于电商后台管理系统来说非常全面了。
  技术选型:
  预览界面:
  
  角色分配也相当明确:
  
  当然它也配备了手机端的项目:
  
  
  都是非常不错的案例,对应的后台代码也有发布出来。后端代码基于 SpringBoot+MyBatis 实现,采用 Docker 容器化部署。有兴趣的小伙伴自行翻阅。
  RuoYi-Vue
  gitee获得⭐ 11.3k
  gitee地址:
  若依是一个开源项目,用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手。
  它有自己的开发文档介绍和使用手册。
  
  
  jeecg-boot
  github获得⭐ 24.6k
  github地址:
  jeecg-boot 号称是一款基于 代码生成器 的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发!
  它可以应用在任何J2EE项目的开发中,尤其适合SAAS项目、企业信息管理系统(MIS)、内部办公系统(OA)、企业资源计划系统(ERP)、客户关系管理系统(CRM)等,其半智能手工Merge的开发方式,可以显著提高开发效率70%以上,极大降低开发成本。
  
  
  内容太多,就不一一截图展示了,有兴趣的小伙伴自行查阅参考吧。另外,这里的数据库设计也相当巧妙!后端的大佬可以参考下。

CmsEasy7.3.8后台任意文件读取漏洞

网站优化优采云 发表了文章 • 0 个评论 • 236 次浏览 • 2022-06-20 12:29 • 来自相关话题

  CmsEasy7.3.8后台任意文件读取漏洞
  想学习交流网络安全技术吗?文末扫码入群
  
  0x01漏洞简述
  
  CmsEasy7.3.8版本中存在后台任意文件读取漏洞,漏洞产生原因是,网站的后台模板编辑功能中atlas.html这个接口没有做好限制和过滤,导致可以读取任意传参文件,例如数据库配置文件。
  0x02知识扩展
  
  CmsEasy(中文名:易通企业CMS),是一款基于PHP+MySql架构的网站内容管理系统,由九州易通科技有限公司开发,系统前台生成html、完全符合SEO、同时有在线客服、潜在客户跟踪、便捷企业网站模板制作、搜索引擎推广等功能的企业网站系统。是国内为数不多可以免费提供模板的企业网站系统。
  Search Engine Optimization,简称SEO:汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。
  0x03风险等级
  
  漏洞的评定结果如下:
  评定方式 等级
  威胁等级严重
  影响面 广泛
  0x04影响版本
  
  CmsEasy7.3.8
  0x05漏洞环境搭建
  
  所需系统环境及配置信息
  靶机
  操作系统:windows7
  IP:172.16.16.71
  攻击机
  操作系统:windows10
  IP:172.16.16.53
  所需工具
  安装步骤
  1、点击下载PHPatudy,下载地址:
  https://public.xp.cn/upgrades/phpStudy_64.zip
  2、解压后双击安装,启动Apache服务和mysql服务。
  
  3、点击下载CmsEasy7.3.8,下载地址:
  https://ftp.cmseasy.cn/CmsEasy ... 0.zip
  4、创建网站,将下载好的Cmseasy解压到phpstudy网站根目录下(安装盘符\phpstudy_pro\WWW),点击网站---->创建网站---->域名为靶机IP 172.16.16.71
  注意:phpstudy的根目录也要设置。根目录选择网站安装的路径即可。
  
  5、选择创建好的站点,点击网站,右边【管理】按钮,在下拉菜单中选择【打开网站】,开始安装。设置好数据库名,用户密码点击开始安装即可。
  6、安装成功(注:太低的浏览器版本无法登陆网站后台)
  
  0x06漏洞验证
  
  1、进入管理界面-->模块-->编辑模板
  
  2、观察模板编辑功能,存在对模板的html文件的读取(查看操作),对应到HTTP请求可以明显看到可控参数。
  3、打开Burp Suite,设置浏览器代理,点击查看,开始抓包。
  4、看到可控参数,手动修改ID后发现这个接口没有做好限制和过滤。CTRL+R发送至reperter(重放)模块,修改ID为
  …/…/config/config_database.php
  点击send发送,发现返回了数据库名和用户密码。
  0x07修复建议
  
  1、升级到7.3.8以上版本。
  2、接口做好限制和过滤。
  
  往期回顾:
  欢迎加入海狼技术交流群:
  海狼科技官方微博:
  如果您遇到网络安全问题
  欢迎致电:0991-8156363
  或发送至:
  新疆海狼科技,您身边的网络安全助理 查看全部

  CmsEasy7.3.8后台任意文件读取漏洞
  想学习交流网络安全技术吗?文末扫码入群
  
  0x01漏洞简述
  
  CmsEasy7.3.8版本中存在后台任意文件读取漏洞,漏洞产生原因是,网站的后台模板编辑功能中atlas.html这个接口没有做好限制和过滤,导致可以读取任意传参文件,例如数据库配置文件。
  0x02知识扩展
  
  CmsEasy(中文名:易通企业CMS),是一款基于PHP+MySql架构的网站内容管理系统,由九州易通科技有限公司开发,系统前台生成html、完全符合SEO、同时有在线客服、潜在客户跟踪、便捷企业网站模板制作、搜索引擎推广等功能的企业网站系统。是国内为数不多可以免费提供模板的企业网站系统。
  Search Engine Optimization,简称SEO:汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。
  0x03风险等级
  
  漏洞的评定结果如下:
  评定方式 等级
  威胁等级严重
  影响面 广泛
  0x04影响版本
  
  CmsEasy7.3.8
  0x05漏洞环境搭建
  
  所需系统环境及配置信息
  靶机
  操作系统:windows7
  IP:172.16.16.71
  攻击机
  操作系统:windows10
  IP:172.16.16.53
  所需工具
  安装步骤
  1、点击下载PHPatudy,下载地址:
  https://public.xp.cn/upgrades/phpStudy_64.zip
  2、解压后双击安装,启动Apache服务和mysql服务。
  
  3、点击下载CmsEasy7.3.8,下载地址:
  https://ftp.cmseasy.cn/CmsEasy ... 0.zip
  4、创建网站,将下载好的Cmseasy解压到phpstudy网站根目录下(安装盘符\phpstudy_pro\WWW),点击网站---->创建网站---->域名为靶机IP 172.16.16.71
  注意:phpstudy的根目录也要设置。根目录选择网站安装的路径即可。
  
  5、选择创建好的站点,点击网站,右边【管理】按钮,在下拉菜单中选择【打开网站】,开始安装。设置好数据库名,用户密码点击开始安装即可。
  6、安装成功(注:太低的浏览器版本无法登陆网站后台)
  
  0x06漏洞验证
  
  1、进入管理界面-->模块-->编辑模板
  
  2、观察模板编辑功能,存在对模板的html文件的读取(查看操作),对应到HTTP请求可以明显看到可控参数。
  3、打开Burp Suite,设置浏览器代理,点击查看,开始抓包。
  4、看到可控参数,手动修改ID后发现这个接口没有做好限制和过滤。CTRL+R发送至reperter(重放)模块,修改ID为
  …/…/config/config_database.php
  点击send发送,发现返回了数据库名和用户密码。
  0x07修复建议
  
  1、升级到7.3.8以上版本。
  2、接口做好限制和过滤。
  
  往期回顾:
  欢迎加入海狼技术交流群:
  海狼科技官方微博:
  如果您遇到网络安全问题
  欢迎致电:0991-8156363
  或发送至:
  新疆海狼科技,您身边的网络安全助理

跨境电商从0到100:企业该如何选择建站系统

网站优化优采云 发表了文章 • 0 个评论 • 92 次浏览 • 2022-06-20 12:09 • 来自相关话题

  跨境电商从0到100:企业该如何选择建站系统
  
  写在前面的话:
  最近跨境圈可谓风起云涌,亚马逊众多头部玩家纷纷暴雷:全部店铺账号被封,几亿甚至是几十亿的资产被套牢,员工晚上打卡,第二天收到企业遣散通知……亚马逊卖家人人自危。
  
  这个时候,大家也都意识到了,拥有自主话语权的网站和品牌是多么的重要。因此独立站成为新的跨境风口。但风口里面也会有砂砾甚至是石头,你碰到了不会死但是可能会受伤或者让你难受一下。在独立站建设过程中,部分人也会遇到一些大坑或者是不靠谱的人,所以我们推出了从独立站到品牌营销系列。帮助大家在认知上了解独立站从建站到优化过程中所涉及的问题以及解决方案,希望可以帮助大家少踩一些坑。大家可以通过链接观看之前的几篇文章:今天要给大家分享的是企业该如何选择建站系统。
  Part 1、常见的建站系统
  市面上常见的建站系统,有两种:传统建站和CMS建站系统
  传统建站
  传统建站,顾名思义,最传统的利用代码建站的方式。利用代码建站是所有建站系统的基础。
  
  但是对于没有代码基础的人来说,这种建站方式难度太高,且后期的修改、操作只能是依靠专业的技术人员,可操控性不强。因此也就衍生出了CMS建站系统。
  CMS建站系统
  CMS,是content management system的缩写,即内容管理系统,是一种用来创建内容的网页模板。简单点来说,就是技术人员利用代码写出来一套程序,你只需要将内容上传上去,系统可自动的生成相关的网页。
  它允许多位成员同时进行创建、编辑、发布。用户上传的内容会存储在数据库中,并基于网站模板进行显示。
  
  对比传统的建站方式,CMS建站系统具有以下的优势:
  大家耳熟能详的Wordpress和Shopify都属于CMS建站系统。
  那么,接下来我们来看一下国内、国外常见的CMS建站系统有哪些,以及各自的优势所在:
  国内常见的CMS建站系统
  在我国,经常使用到的建站系统有PageAdmin、织梦DEDECMS、帝国系统, PHPCMS系统等不同的CMS系统,那么我们来看一下这些系统都有哪些区别以及优劣势。
  PageAdmin CMS建站系统(⭐️⭐️⭐️⭐️⭐️)
  PageAdmin CMS建站系统()是国内应用最受欢迎的建站系统之一,大部分的外贸网站都是PageAdmin建成的。它的模板丰富、功能强大、可拓展性强,可以轻松的帮你打造一个独具特色的网站,那么我们来盘点一下,该系统的优缺点:
  优点:
  缺点:
  织梦 DEDE CMS(⭐️⭐️)
  织梦也是国内知名的老牌建站系统了,主要是面向中小企业以及个人站长的新闻内容管理平台。但是其原始创作团队解散之后,这一系统已经不再进行更新和维护了,因此我们看到的织梦DEDE CMS的操作后台比较老化。
  
  织梦DEDE CMS的模板较为简单,可拓展性很差,适合没有定制需求的新手来进行操作。其最令人诟病的地方就是网站的安全性方面,因为织梦是开源的,所以DEDE做的站经常被黑,这个已经是众所周知的事情。
  优点:
  缺点:
  帝国CMS(⭐️⭐️⭐️)
  
  帝国CMS建站系统()是2002年推出的一款CMS建站系统,系统采用老式的表格布局模式,后台非常的复杂,因此对于新手来说不友好。但是其模板标签拓展灵活,但是需要用户有一定的代码基础。
  优点:
  缺点:
  PHPCMS(⭐️⭐️)
  
  PHPCMS适合用来进行二次开发,它的系统底层架构做得不错,承载也很强大,但是需要开发者掌握Html ,PHP, Mysql等技术语言。技术采用模块化方式开发,功能易用便于扩展,采用mvc模式,技术相对其他cms来说,算新的。可惜的是phpcms在2020年初已经关站倒闭。建议大家谨慎选择。
  优点:
  缺点:
  以上的这些就是企业站经常使用到的国内的建站系统。除了这些系统以外,还有一些专门建站博客或者是新闻网站的建站程序,这里大家可以参考一下:
  国外常见的CMS建站系统
  说到国外的CMS建站系统,Wordpress, Shopify, Magento, Bigcommerce等系统都是大家耳熟能详的建站系统,除此以外,还有其他一些在国外比较常用,但是国内很少用到的系统,比如Joomla,Durpal, Sharepoint等。在这里我们来看一下这些网站的优劣势:
  Wordpress建站系统(⭐️⭐️⭐️⭐️⭐️)
  
  Wordpress系统是全球使用最广泛的开源CMS建站系统, 互联网上35%的网站是由WordPress系统建设而成。该平台是在2003年推出,此后凭借简单易上手的操作后台,丰富的模板和插件、良好的拓展性,使其在众多的CMS建站系统中脱颖而出。
  优点:
  缺点:
  Shopify建站系统(⭐️⭐️⭐️⭐️)
  Shopify是一个托管电子商务平台,专门用来建设在线零售商店。这一系统非常适合新手网上开店,无需购买任何主机、管理备份和安全,只需要支付29-299美金,你就可以使用Shopify系统了。
  
  除了最基础的版本, Shopify还推出了每月2000美金的Shopify Plus计划, 与之相对应的是更全面的功能:专属的客户经理、更多的主题和App选择、产品页面支持AR, Video, 3D视频、同一面板同时管理多个Shopify店铺, 更加细致的数据分析功能以及优化完善后的支付系统等。
  优点:
  缺点:
  Magento(⭐️⭐️⭐️⭐️)
  
  Magento是 Adobe 旗下的电子商务平台,可以为精通代码技术的店主提供无限可能。Magento提供两个版本的建站系统: Magento Open Source 和 Magento Commerce.
  使用Magento Open Source,你可以下载一个免费的开源建站系统
  那么 Magento Commerce就是专门针对商业方面的建站了,收费比较昂贵。
  优点:
  缺点:
  Bigcommerce(⭐️⭐️⭐️⭐️)
  Bigcommerce是一个一体化的在线电子商务平台,它的性质和Shopify差不多。如果你对代码一窍不通,那么这个平台的话,很适合你。
  
  Bigcommerce平台是收费的,但是你可以免费试用。因为平台是一站式的管理系统,所以不需要额外的购买服务器、域名(域名平台可以免费提供,类似于,当然你也可以自行购买)。
  平台提供丰富的模板和插件,可以实现高度的自定义设计。因为主要为电子商务设计,所以可以在不影响速度的前提下,上传大量的产品、图片和文章。后台操作界面非常的清晰,简单,适合新手操作。
  优点:
  缺点:
  Joomla(⭐️⭐️⭐️)
  
  Joomla也是一个免费的开源CMS建站系统。平台成立于2005年。它和Wordpress一样,已经发展了很多年,而且平台中模板和插件非常的丰富,可拓展性非常的强。对比其他的建站系统,Joomla拥有更强大的内置功能。依靠其内置功能,用户可以轻松的使用多语言创建页面,以及创建不同模板和类型的文章页面等。但是在国内的话,很少有企业使用这一系统,因此相关的技术人员也很难找到。
  优点:
  缺点:
  Drupal(⭐️⭐️⭐️)
  Drupal也是一个开源的CMS系统,可以用来创建大型网站、个人博客和新闻网站等。由于该平台是专门为研发人员进行设计的,所以使用者必须要对 PHP、HTML 和 CSS 有一定的了解才能充分的利用Drupal的全部功能。
  
  Drupal CMS建站功能拥有数千个模板和插件可供选择,可实现高度的自定义设计功能。多语言功能内置到系统中,可以轻松实现多语言切换。另外,其安全性也是所有的CMS建站系统中首屈一指的。
  优点:
  缺点:
  Part2、外贸企业挑选建站系统注意事项
  上面我们盘点了那么多的建站系统,那么我们该选择哪一个呢?在选择之前,建议大家从以下的角度来进行考量
  1、系统的易用性
  优秀的CMS系统,可以让你非常简单轻松的就能上传、编辑管理你的内容。这种系统的后台一般都支持拖放功能,可以让你在页面中添加不同的模块和元素。
  2、系统功能完善、成熟度高、用户量大
  只有系统功能完善的CMS系统才能实现你对网站的所有设想。如果系统不完善,不成熟的话,会导致功能无法实现,影响网站的建设。系统功能完善,成熟度高、用户量大、这样的系统才有较高的实用性,满足企业的基础功能需求,利于后期自行维护
  3、安全性(非常重要!!!)
  CMS系统的安全性是我们需要重点衡量的一个因素,毕竟好不容易建了一个网站,谁都不希望这个网站受到黑客的攻击。所以CMS系统是不是经常进行更新,安装补丁,以及是否有相关的工作人员/社区进行技术上的支持就非常的重要了。除了系统的安全性,我们还要考虑到数据信息的安全性。其中包括流量信息、订单信息、客户信息等。如果这些数据可以被第三方轻易的获取,那么网站的损失就大了。
  4、系统是否是开源系统
  国外的大多数CMS建站系统都是开源系统。开源系统意味着代码向公众进行开放,易用性就会比较高。你可以轻松的在建站公司那边获得网站源代码(国内很多公司自己的系统,是不会提供共源代码给你的,也就意味着你只是租了一个房间,最终的所有的东西都还是建站公司的。)
  5、模板和插件的丰富度
  模板和插件比较多的话,可以提供更高的自由度来修改我们的网站。可拓展性比较强
  6、搜索引擎优化
  CMS系统是否针对搜索引擎进行过优化,以及是否有第三方的插件支持网站进行搜索引擎优化。毕竟网站建了之后就是要在搜索引擎上面做排名的。如果CMS系统对搜索引擎不友好的话,网站建设了意义也不大。
  7、售后以及技术支持
  网站就像一台庞大的机器,当这个机器出问题了,你需要看一下,是不是有足够的技术支持可以帮助你解决这一问题。找不到技术支持,或者解决问题速度太慢,都会影响网站的正常工作。
  结合以上的7种元素,在这里推荐大家使用以下的建站系统进行建站:
  那么接下来,我们以WordPress为例,教给大家如何7步建成独立站。
  Part3、7步建成独立站
  01
  挑选域名
  在建站之前,你要先确定你的网站名称,并购买域名。选择一个合适的域名没有那么简单的。关于如何挑选域名,可参考我们之前的文章-《
  02
  挑选服务器
  关于如何挑选服务器,可参考我们之前的文章-《
  03
  安装Wordpress
  不管你的服务器,挑选的是Siteground, Bluehost, 还是Inmotion Hosting, 这些大的网站后台都集成了WordPress安装,只需要简单的操作即可进行安装,在这里,以Inmotion Hosting为例,
  1、登陆Inmotion Hosting控制面板-cPanel
  2、找到Software板块,点击 Softaculous Apps installer
  
  3、点开后选择Wordpress的标志,点开就能看到安装的界面,点击“install”进行安装
  4、按照要求填写WordPress安装信息
  5、Softaculous Apps installer会检查你填写和提交的数据,并将wordpress文件安装到你的服务器上面。点击返回概览,你会在当前安装列表中看到你的WordPress安装进度。
  
  04
  挑选模板并进行自定义
  网站除了要有优秀的文字内容来吸引用户外,还需要有漂亮的网页设计。Wordpress系统中提供了大量的免费和付费的网站模板可供用户来进行选择,我们只需要点开Wordpress后台Apperance-Themes就可以看到系统提供的免费模板。
  
  点击“Add New" 进入模板库,在模板库里面选择自己心仪的网站模板进行安装并激活就可以应用到网站上面。
  
  除了在worpress模板库里面直接安装模板,我们还可以到第三方网站上面去购买WordPress的模板。很多第三方网站上面的WordPress模板是专业的技术人员进行开发或者是优化过后的,展示效果和优化效果都很好。
  著名的WordPress模板出售网站有以下几个:
  在这些网站上面购买的模板有另外一种方法进行安装:登陆Wordpress后台-点击Apperance-Add New
  进去之后,点击 Upload Theme,将你从第三方网站上购买到的WordPress模板文件.zip上传,激活并安装。
  
  之后,我们可以对挑选的模板进行自定义,选择喜欢的样式、文字颜色和排版等。当然也可以安装必要的WordPress插件,比如排版插件Elementer, SEO插件Yoast SEO等
  05
  上传内容
  利用Wordpress后台提供的功能项上传文字、图片和视频即可:
  
  06
  预览&测试网站
  上传了基础页面,产品以及文章内容,我们就可以对网站进行预览,看网站实现的展示效果是否是我们想要的。以及想要的的功能能否全部实现。如果预览测试合格,那么就可以大规模的上传产品和文章内容,并实施SEO优化。
  
  如果功能实现不理想的话,就需要对网站进行调整、修改。
  07
  发布网站&进行营销工作
  确保我们的网站没有问题了,我们就可以发布网站,让谷歌对网站进行收录。并安排之后的网站营销工作,比如SEO优化,谷歌广告或者是社交引流等.
  如果大家对于如何选择建站系统有任何的疑问,欢迎大家在下方进行留言。
  END
  想要学习更多外贸SEO知识,可以通过以下方式找到我们:
   查看全部

  跨境电商从0到100:企业该如何选择建站系统
  
  写在前面的话:
  最近跨境圈可谓风起云涌,亚马逊众多头部玩家纷纷暴雷:全部店铺账号被封,几亿甚至是几十亿的资产被套牢,员工晚上打卡,第二天收到企业遣散通知……亚马逊卖家人人自危。
  
  这个时候,大家也都意识到了,拥有自主话语权的网站和品牌是多么的重要。因此独立站成为新的跨境风口。但风口里面也会有砂砾甚至是石头,你碰到了不会死但是可能会受伤或者让你难受一下。在独立站建设过程中,部分人也会遇到一些大坑或者是不靠谱的人,所以我们推出了从独立站到品牌营销系列。帮助大家在认知上了解独立站从建站到优化过程中所涉及的问题以及解决方案,希望可以帮助大家少踩一些坑。大家可以通过链接观看之前的几篇文章:今天要给大家分享的是企业该如何选择建站系统。
  Part 1、常见的建站系统
  市面上常见的建站系统,有两种:传统建站和CMS建站系统
  传统建站
  传统建站,顾名思义,最传统的利用代码建站的方式。利用代码建站是所有建站系统的基础。
  
  但是对于没有代码基础的人来说,这种建站方式难度太高,且后期的修改、操作只能是依靠专业的技术人员,可操控性不强。因此也就衍生出了CMS建站系统。
  CMS建站系统
  CMS,是content management system的缩写,即内容管理系统,是一种用来创建内容的网页模板。简单点来说,就是技术人员利用代码写出来一套程序,你只需要将内容上传上去,系统可自动的生成相关的网页。
  它允许多位成员同时进行创建、编辑、发布。用户上传的内容会存储在数据库中,并基于网站模板进行显示。
  
  对比传统的建站方式,CMS建站系统具有以下的优势:
  大家耳熟能详的Wordpress和Shopify都属于CMS建站系统。
  那么,接下来我们来看一下国内、国外常见的CMS建站系统有哪些,以及各自的优势所在:
  国内常见的CMS建站系统
  在我国,经常使用到的建站系统有PageAdmin、织梦DEDECMS、帝国系统, PHPCMS系统等不同的CMS系统,那么我们来看一下这些系统都有哪些区别以及优劣势。
  PageAdmin CMS建站系统(⭐️⭐️⭐️⭐️⭐️)
  PageAdmin CMS建站系统()是国内应用最受欢迎的建站系统之一,大部分的外贸网站都是PageAdmin建成的。它的模板丰富、功能强大、可拓展性强,可以轻松的帮你打造一个独具特色的网站,那么我们来盘点一下,该系统的优缺点:
  优点:
  缺点:
  织梦 DEDE CMS(⭐️⭐️)
  织梦也是国内知名的老牌建站系统了,主要是面向中小企业以及个人站长的新闻内容管理平台。但是其原始创作团队解散之后,这一系统已经不再进行更新和维护了,因此我们看到的织梦DEDE CMS的操作后台比较老化。
  
  织梦DEDE CMS的模板较为简单,可拓展性很差,适合没有定制需求的新手来进行操作。其最令人诟病的地方就是网站的安全性方面,因为织梦是开源的,所以DEDE做的站经常被黑,这个已经是众所周知的事情。
  优点:
  缺点:
  帝国CMS(⭐️⭐️⭐️)
  
  帝国CMS建站系统()是2002年推出的一款CMS建站系统,系统采用老式的表格布局模式,后台非常的复杂,因此对于新手来说不友好。但是其模板标签拓展灵活,但是需要用户有一定的代码基础。
  优点:
  缺点:
  PHPCMS(⭐️⭐️)
  
  PHPCMS适合用来进行二次开发,它的系统底层架构做得不错,承载也很强大,但是需要开发者掌握Html ,PHP, Mysql等技术语言。技术采用模块化方式开发,功能易用便于扩展,采用mvc模式,技术相对其他cms来说,算新的。可惜的是phpcms在2020年初已经关站倒闭。建议大家谨慎选择。
  优点:
  缺点:
  以上的这些就是企业站经常使用到的国内的建站系统。除了这些系统以外,还有一些专门建站博客或者是新闻网站的建站程序,这里大家可以参考一下:
  国外常见的CMS建站系统
  说到国外的CMS建站系统,Wordpress, Shopify, Magento, Bigcommerce等系统都是大家耳熟能详的建站系统,除此以外,还有其他一些在国外比较常用,但是国内很少用到的系统,比如Joomla,Durpal, Sharepoint等。在这里我们来看一下这些网站的优劣势:
  Wordpress建站系统(⭐️⭐️⭐️⭐️⭐️)
  
  Wordpress系统是全球使用最广泛的开源CMS建站系统, 互联网上35%的网站是由WordPress系统建设而成。该平台是在2003年推出,此后凭借简单易上手的操作后台,丰富的模板和插件、良好的拓展性,使其在众多的CMS建站系统中脱颖而出。
  优点:
  缺点:
  Shopify建站系统(⭐️⭐️⭐️⭐️)
  Shopify是一个托管电子商务平台,专门用来建设在线零售商店。这一系统非常适合新手网上开店,无需购买任何主机、管理备份和安全,只需要支付29-299美金,你就可以使用Shopify系统了。
  
  除了最基础的版本, Shopify还推出了每月2000美金的Shopify Plus计划, 与之相对应的是更全面的功能:专属的客户经理、更多的主题和App选择、产品页面支持AR, Video, 3D视频、同一面板同时管理多个Shopify店铺, 更加细致的数据分析功能以及优化完善后的支付系统等。
  优点:
  缺点:
  Magento(⭐️⭐️⭐️⭐️)
  
  Magento是 Adobe 旗下的电子商务平台,可以为精通代码技术的店主提供无限可能。Magento提供两个版本的建站系统: Magento Open Source 和 Magento Commerce.
  使用Magento Open Source,你可以下载一个免费的开源建站系统
  那么 Magento Commerce就是专门针对商业方面的建站了,收费比较昂贵。
  优点:
  缺点:
  Bigcommerce(⭐️⭐️⭐️⭐️)
  Bigcommerce是一个一体化的在线电子商务平台,它的性质和Shopify差不多。如果你对代码一窍不通,那么这个平台的话,很适合你。
  
  Bigcommerce平台是收费的,但是你可以免费试用。因为平台是一站式的管理系统,所以不需要额外的购买服务器、域名(域名平台可以免费提供,类似于,当然你也可以自行购买)。
  平台提供丰富的模板和插件,可以实现高度的自定义设计。因为主要为电子商务设计,所以可以在不影响速度的前提下,上传大量的产品、图片和文章。后台操作界面非常的清晰,简单,适合新手操作。
  优点:
  缺点:
  Joomla(⭐️⭐️⭐️)
  
  Joomla也是一个免费的开源CMS建站系统。平台成立于2005年。它和Wordpress一样,已经发展了很多年,而且平台中模板和插件非常的丰富,可拓展性非常的强。对比其他的建站系统,Joomla拥有更强大的内置功能。依靠其内置功能,用户可以轻松的使用多语言创建页面,以及创建不同模板和类型的文章页面等。但是在国内的话,很少有企业使用这一系统,因此相关的技术人员也很难找到。
  优点:
  缺点:
  Drupal(⭐️⭐️⭐️)
  Drupal也是一个开源的CMS系统,可以用来创建大型网站、个人博客和新闻网站等。由于该平台是专门为研发人员进行设计的,所以使用者必须要对 PHP、HTML 和 CSS 有一定的了解才能充分的利用Drupal的全部功能。
  
  Drupal CMS建站功能拥有数千个模板和插件可供选择,可实现高度的自定义设计功能。多语言功能内置到系统中,可以轻松实现多语言切换。另外,其安全性也是所有的CMS建站系统中首屈一指的。
  优点:
  缺点:
  Part2、外贸企业挑选建站系统注意事项
  上面我们盘点了那么多的建站系统,那么我们该选择哪一个呢?在选择之前,建议大家从以下的角度来进行考量
  1、系统的易用性
  优秀的CMS系统,可以让你非常简单轻松的就能上传、编辑管理你的内容。这种系统的后台一般都支持拖放功能,可以让你在页面中添加不同的模块和元素。
  2、系统功能完善、成熟度高、用户量大
  只有系统功能完善的CMS系统才能实现你对网站的所有设想。如果系统不完善,不成熟的话,会导致功能无法实现,影响网站的建设。系统功能完善,成熟度高、用户量大、这样的系统才有较高的实用性,满足企业的基础功能需求,利于后期自行维护
  3、安全性(非常重要!!!)
  CMS系统的安全性是我们需要重点衡量的一个因素,毕竟好不容易建了一个网站,谁都不希望这个网站受到黑客的攻击。所以CMS系统是不是经常进行更新,安装补丁,以及是否有相关的工作人员/社区进行技术上的支持就非常的重要了。除了系统的安全性,我们还要考虑到数据信息的安全性。其中包括流量信息、订单信息、客户信息等。如果这些数据可以被第三方轻易的获取,那么网站的损失就大了。
  4、系统是否是开源系统
  国外的大多数CMS建站系统都是开源系统。开源系统意味着代码向公众进行开放,易用性就会比较高。你可以轻松的在建站公司那边获得网站源代码(国内很多公司自己的系统,是不会提供共源代码给你的,也就意味着你只是租了一个房间,最终的所有的东西都还是建站公司的。)
  5、模板和插件的丰富度
  模板和插件比较多的话,可以提供更高的自由度来修改我们的网站。可拓展性比较强
  6、搜索引擎优化
  CMS系统是否针对搜索引擎进行过优化,以及是否有第三方的插件支持网站进行搜索引擎优化。毕竟网站建了之后就是要在搜索引擎上面做排名的。如果CMS系统对搜索引擎不友好的话,网站建设了意义也不大。
  7、售后以及技术支持
  网站就像一台庞大的机器,当这个机器出问题了,你需要看一下,是不是有足够的技术支持可以帮助你解决这一问题。找不到技术支持,或者解决问题速度太慢,都会影响网站的正常工作。
  结合以上的7种元素,在这里推荐大家使用以下的建站系统进行建站:
  那么接下来,我们以WordPress为例,教给大家如何7步建成独立站。
  Part3、7步建成独立站
  01
  挑选域名
  在建站之前,你要先确定你的网站名称,并购买域名。选择一个合适的域名没有那么简单的。关于如何挑选域名,可参考我们之前的文章-《
  02
  挑选服务器
  关于如何挑选服务器,可参考我们之前的文章-《
  03
  安装Wordpress
  不管你的服务器,挑选的是Siteground, Bluehost, 还是Inmotion Hosting, 这些大的网站后台都集成了WordPress安装,只需要简单的操作即可进行安装,在这里,以Inmotion Hosting为例,
  1、登陆Inmotion Hosting控制面板-cPanel
  2、找到Software板块,点击 Softaculous Apps installer
  
  3、点开后选择Wordpress的标志,点开就能看到安装的界面,点击“install”进行安装
  4、按照要求填写WordPress安装信息
  5、Softaculous Apps installer会检查你填写和提交的数据,并将wordpress文件安装到你的服务器上面。点击返回概览,你会在当前安装列表中看到你的WordPress安装进度。
  
  04
  挑选模板并进行自定义
  网站除了要有优秀的文字内容来吸引用户外,还需要有漂亮的网页设计。Wordpress系统中提供了大量的免费和付费的网站模板可供用户来进行选择,我们只需要点开Wordpress后台Apperance-Themes就可以看到系统提供的免费模板。
  
  点击“Add New" 进入模板库,在模板库里面选择自己心仪的网站模板进行安装并激活就可以应用到网站上面。
  
  除了在worpress模板库里面直接安装模板,我们还可以到第三方网站上面去购买WordPress的模板。很多第三方网站上面的WordPress模板是专业的技术人员进行开发或者是优化过后的,展示效果和优化效果都很好。
  著名的WordPress模板出售网站有以下几个:
  在这些网站上面购买的模板有另外一种方法进行安装:登陆Wordpress后台-点击Apperance-Add New
  进去之后,点击 Upload Theme,将你从第三方网站上购买到的WordPress模板文件.zip上传,激活并安装。
  
  之后,我们可以对挑选的模板进行自定义,选择喜欢的样式、文字颜色和排版等。当然也可以安装必要的WordPress插件,比如排版插件Elementer, SEO插件Yoast SEO等
  05
  上传内容
  利用Wordpress后台提供的功能项上传文字、图片和视频即可:
  
  06
  预览&测试网站
  上传了基础页面,产品以及文章内容,我们就可以对网站进行预览,看网站实现的展示效果是否是我们想要的。以及想要的的功能能否全部实现。如果预览测试合格,那么就可以大规模的上传产品和文章内容,并实施SEO优化。
  
  如果功能实现不理想的话,就需要对网站进行调整、修改。
  07
  发布网站&进行营销工作
  确保我们的网站没有问题了,我们就可以发布网站,让谷歌对网站进行收录。并安排之后的网站营销工作,比如SEO优化,谷歌广告或者是社交引流等.
  如果大家对于如何选择建站系统有任何的疑问,欢迎大家在下方进行留言。
  END
  想要学习更多外贸SEO知识,可以通过以下方式找到我们:
  

Python识别CMS与批量资产收集拓展

网站优化优采云 发表了文章 • 0 个评论 • 99 次浏览 • 2022-06-18 18:53 • 来自相关话题

  Python识别CMS与批量资产收集拓展
  使用模板的话,网站的结构重复度太高,不利于搜索引擎优化
  回归到本文的主旨,在渗透测试中检测目标网址是否基于CMS模板开发,判断使用的CMS类型是非常重要的一步,可以查找网上已曝光的CMS程序漏洞,运气好能一步到位拿到权限,如果该CMS系统开源,还能下载相对应的源码进行代码审计。
  根据个人经验,总结一下识别网站CMS类型的五种方法,本质上都是根据网页内容或者网页文件的特征进行识别。只是根据不同类型的网页大概分成五类,方便理解和阅读,至于在网上找到在线识别CMS网站的接口然后加到爬虫中,省时省力却不在本文的讨论范围之内,当然会在以后视频课程的爬虫专栏会专门讲。
  根据页面内容识别CMS类型
  许多CMS系统会在网站的首页加上一些象征该CMS的关键词,举个例子,WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设自己的网站,如果使用该程序搭建网站,会在该网站的首页出现关键词。下图目标网址案例就是使用WordPress搭建:
  
  我们策略判断该网址是使用WordPress系统搭建的,这样我们识别出来后,就继续确认该网站使用Wordpress的版本号,然后搜索该版本是否出现过相关漏洞,方便下一步渗透测试工作的进行。
  
  那么只需要准备一个指纹库,然后访问目标网站后,对照指纹库的内容,如果命中关键词,则直接判断该网址的CMS类型。
  
  指纹库文件需要不断地收集更新整理,本文中整理好的指纹库获取方式放在文末自取。
  如果使用代码实现,粗略的大体结构大概就是如下设计:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCmsFromBody(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in url_content:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                print('目标网址:{} 识别CMS为:{}'.format(url,v))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except Exception as e:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        print(e)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />CheckCmsFromBody(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  代码粗略功能就是获取首页的内容,然后从指纹库寻找是否出现关键词判定CMS类型。
  根据请求头内容识别CMS类型
  除了上文中从网页内容识别CMS类型,还可以从请求头消息中获取相关信息,某些CMS系统返回的请求头信息中也会添加独特的特征码。如下图目标网站就是使用PowerEasy(动易系统)搭建的网站,可以直接从请求头中获取到特征码,从而判断出使用CMS的类型。
  
  所以在渗透测试的信息收集中,对任何地方都不要放过呀~细心谨慎才能挖到更多的信息。
  这个使用代码实现太简单了,会的同学都懒得看,没有基础的同学看了也看不懂…就不写了…
  主要难点还是在于请求头指纹库的收集与更新。
  
  需要注意的是,请求头是一个字典格式的数据,你需要先把它转换成字符串后,然后再去指纹库寻找特征关键词。
  根据robots.txt文件识别CMS类型
  渗透测试中,robots.txt一定是都会尝试访问的一个文件,robots协议也叫robots.txt是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的哪些文件目录不能访问,哪些可以访问,网站管理员不想让搜索引擎访问的目录是不是含有敏感信息呢?
  答案是的,有些CMS系统会将一些敏感的目录,比如后台管理界面等不允许搜索引擎抓取,也会将一些独特的特征码放入该文件中,以此我们可以根据特征文本关键词进行判定。下图目标网站使用的是PHPCMS v9搭建的系统,通过访问robots文件对比特征码就很容易的识别出使用的CMS类型。
  
  所以还可以根据robots文件的内容方法进行CMS识别。
  根据网站文件md5值识别CMS类型
  MD5指纹(文件指纹验证)当你从网络上下载了软件后,想确保此软件没有被人修改过(如添加了病毒/非官方插件),或在下载中被破坏,可以用文件指纹验证(MD5)技术进行确认。
  原理:
  通过某种算法,对具体的文件进行校验,得出了一个32位的十六进制数(校验和)。待校验文件的文件名和后缀名都可以更改,不影响校核。由于原来的信息只要有稍许改动,通过md5运算后,结果都会有很大的改变。所以,如果再次校验以后所得到的值(md5代码)和此软件发布站或官方网站公布的值不同,就可以认为,文件已被改动过。
  需要注意的是,每个文件对应的MD5的值是不一样的,那么回归到本文主旨,当你使用一套完整的CMS系统的时候,下载了该CMS系统包含的CSS,字体,图标文件,这些文件中有些都是该CMS系统特有的,访问该文件如果该文件存在,然后校验该文件的MD5值,如果与指纹库中一致,则可以判断该网站的CMS类型,该方法相对前面准确率较高。
  指纹库格式是这样:
  网站文件|CMS类型|网站文件的MD5值。<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/static/image/admincp/cloud/qun_op.png|DISCUZ|AB35FA459B0BB01D31BA8FAD0953FCC9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/widget/images/thumbnail.jpg|ECSHOP|7BB50E4281FA02758834A2E9D7BA9FB9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/js/calendar/active-bg.gif|ECSHOP|F8FB9F2B7428C94B41320AA1BC9CF601|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/phpcms/libs/data/font/Vineta.ttf|PHPCMS|E6E557BAD69B09533827D9652E0C11AB|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/statics/images/admin_img/arrowhead-y.png|PHPCMS|6C34F70BD2A05C8C5DDEBB369B5B9509|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  即网站加上网站文件的网址,获取该文件的MD5值,对照指纹库的值是否一致,如果一致则确认该网站使用的CMS类型。python实现识别方式使用代码实现也就四五行,我们假设案例,假设一个指纹库:
  upload/my_girl.jpg|HEXO|587c7132e6043a1de24e03ededa8980d<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  然后使用代码实践进行识别:
  import hashlib,requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />URL = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />req = requests.get(url=URL+'/upload/my_girl.jpg')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5.update(req.content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if md5.hexdigest() == '587c7132e6043a1de24e03ededa8980d':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print('目标网址CMS类型为:HEXO')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试代码结果如下:
  
  根据指定网页内容识别CMS类型
  此类方法结合了上面几种情况下的指纹库,即CMS系统中默认包含一些网页或者文本,这些文本在你搭建好系统后任然存在,你访问这些网页或者文本,然后查看网页文本中是否存在特定的关键词,如果存在就确认CMS类型。
  如下文目标网址使用EmpireCMS(帝国网站管理系统)搭建,访问该网站的:
  e/admin/adminstyle/1/page/about.htm<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  文件,发现该页面存在,然后命中关键词,得出结果该网址使用的帝国网站管理系统搭建而成。
  字典中触发关键词识别,判定为帝国网址管理系统。
  
  补充说明
  除了上面五种访问不同文件类型,然后根据指纹库判定CMS类型,有些时候还可以通过访问错误页面获取信息,这时候可能会遇到防火墙阻拦。
  或者有些网站会对目录做一些修改,可以根据实际情况修改扫描代码,自定义添加二级目录扫描对照指纹库有时候也能发现很多敏感信息。
  上面五种方法中,按照准确率由高到低排序为:
  MD5值校验识别>指定网页内容识别>Robots.txt文件识别>请求头信息识别>首页内容识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  按照扫描需要的时间由低到高排序为:
  首页内容识别=请求头信息识别=Robots.txt文件识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  因为首页内容识别、请求头信息识别、Robots.txt文件识别只用访问一次该网站,不会产生大量的扫描,成功与否主要取决于你的指纹库。如果要扫描指定网页内容和校验MD5值,则会产生较多甚至大量的访问扫描,很容易触发防火墙引起很多麻烦事情上身,当然这些都可以通过降低扫描频率、自动随机切换代理IP、分布式低频率扫描等多种手段绕过。
  回归到本文主旨,识别CMS类型最最重要还得依赖强大的指纹库,甚至可以说完全依赖于指纹库的数据,五种方法只是思路的一个分类,能不能产出结果还是要靠指纹库的,关于如何更新整理指纹库,可以在GitHub上收集整理,各大论坛也有好心人专门整理,当然你也可以自己下载多套CMS系统,然后自己分析哪些文件是CMS独有的,校验出MD5值或者考察关键词等等清洗数据后加入更新到你的指纹库。
  Python识别CMS代码工程设计实现与拓展
  虽然整个工程看上去很多东西挺复杂,但是仔细去分析各个功能模块就会发现很容易实现,你需要做的就是把每个功能单独完成后,整体搭建在一起形成一套流程即可。下面演示代码为大致流程,方便阅读理解。
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  所以只需要访问一次网址的首页,拿到首页内容和请求头信息先对比,访问robots.txt文件检测,最后扫描指定网页内容检测关键词和验证MD5值。
  具体流程图:
  
  代码实现如下:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 指纹库信息,因为我收集了差不多5000条指纹,如果全部放在代码中,则文章就写不下了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 本代码仅作演示案例的工程结构<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 关于优化以及拓展,详细会在文章中介绍<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 首页内容指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 请求头信息指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># robots文件指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># MD5指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 特定网页指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 最后根据MD5值判定,其实如果前面都没有判定出来的话,这里扫描的意义也不是很大<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in cms_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_s = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_s)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5.update(res[1])<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            rmd5 = md5.hexdigest()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 == rmd5:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if __name__ == '__main__':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print(CheckCMS(url))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试结果:
  以上大致就是使用代码识别CMS类型的流程,有代码基础的同学可以自己进行拓展,举几个例子:
  加入WAF识别功能,即调用特定网页内容鉴定和MD5值校验之前,启动WAF识别,如果发现存在WAF就自行跳过,关于WAF识别的代码在公众号上两篇文章有源代码
  加入随机请求头,随机代理IP等条件,伪装成浏览器
  对网站的目录进行爬行,然后抓取爬行网页的内容对比参照指纹库关键词,有些时候也能命中不少,因为一些关键词不一定出现在首页,也有可能出现在错误页面或者404页面中
  引入线程池,实现批量扫描网址然后识别CMS类型后保存在文本,同样可以实现批量刷洞的效果,不过这种做法有涉及到HC的嫌疑,所以如果不是业务需求还是不要去做
  寻找多个在线识别CMS的接口,然后写个爬虫,结合在一起识别,当然这个如果作为长期使用的话,还得定期检查接口是否有效
  单单仅凭靠首页内容关键词判定CMS类型,其实是存在较大的误报率,可以结合robots文件等一起结合判断
  可以结合其他知识点做出有意思的东西,主要是要把自己的思维拓展开,比如结合Flask做一个简易版在线版识别CMS,也就十几行代码。一时手痒写一个,图个乐吧大家….
  代码如下:
  # coding:utf-8<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />from flask import Flask,request<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />app = Flask(__name__)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit ! 查看全部

  Python识别CMS与批量资产收集拓展
  使用模板的话,网站的结构重复度太高,不利于搜索引擎优化
  回归到本文的主旨,在渗透测试中检测目标网址是否基于CMS模板开发,判断使用的CMS类型是非常重要的一步,可以查找网上已曝光的CMS程序漏洞,运气好能一步到位拿到权限,如果该CMS系统开源,还能下载相对应的源码进行代码审计。
  根据个人经验,总结一下识别网站CMS类型的五种方法,本质上都是根据网页内容或者网页文件的特征进行识别。只是根据不同类型的网页大概分成五类,方便理解和阅读,至于在网上找到在线识别CMS网站的接口然后加到爬虫中,省时省力却不在本文的讨论范围之内,当然会在以后视频课程的爬虫专栏会专门讲。
  根据页面内容识别CMS类型
  许多CMS系统会在网站的首页加上一些象征该CMS的关键词,举个例子,WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设自己的网站,如果使用该程序搭建网站,会在该网站的首页出现关键词。下图目标网址案例就是使用WordPress搭建:
  
  我们策略判断该网址是使用WordPress系统搭建的,这样我们识别出来后,就继续确认该网站使用Wordpress的版本号,然后搜索该版本是否出现过相关漏洞,方便下一步渗透测试工作的进行。
  
  那么只需要准备一个指纹库,然后访问目标网站后,对照指纹库的内容,如果命中关键词,则直接判断该网址的CMS类型。
  
  指纹库文件需要不断地收集更新整理,本文中整理好的指纹库获取方式放在文末自取。
  如果使用代码实现,粗略的大体结构大概就是如下设计:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCmsFromBody(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in url_content:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                print('目标网址:{} 识别CMS为:{}'.format(url,v))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except Exception as e:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        print(e)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />CheckCmsFromBody(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  代码粗略功能就是获取首页的内容,然后从指纹库寻找是否出现关键词判定CMS类型。
  根据请求头内容识别CMS类型
  除了上文中从网页内容识别CMS类型,还可以从请求头消息中获取相关信息,某些CMS系统返回的请求头信息中也会添加独特的特征码。如下图目标网站就是使用PowerEasy(动易系统)搭建的网站,可以直接从请求头中获取到特征码,从而判断出使用CMS的类型。
  
  所以在渗透测试的信息收集中,对任何地方都不要放过呀~细心谨慎才能挖到更多的信息。
  这个使用代码实现太简单了,会的同学都懒得看,没有基础的同学看了也看不懂…就不写了…
  主要难点还是在于请求头指纹库的收集与更新。
  
  需要注意的是,请求头是一个字典格式的数据,你需要先把它转换成字符串后,然后再去指纹库寻找特征关键词。
  根据robots.txt文件识别CMS类型
  渗透测试中,robots.txt一定是都会尝试访问的一个文件,robots协议也叫robots.txt是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的哪些文件目录不能访问,哪些可以访问,网站管理员不想让搜索引擎访问的目录是不是含有敏感信息呢?
  答案是的,有些CMS系统会将一些敏感的目录,比如后台管理界面等不允许搜索引擎抓取,也会将一些独特的特征码放入该文件中,以此我们可以根据特征文本关键词进行判定。下图目标网站使用的是PHPCMS v9搭建的系统,通过访问robots文件对比特征码就很容易的识别出使用的CMS类型。
  
  所以还可以根据robots文件的内容方法进行CMS识别。
  根据网站文件md5值识别CMS类型
  MD5指纹(文件指纹验证)当你从网络上下载了软件后,想确保此软件没有被人修改过(如添加了病毒/非官方插件),或在下载中被破坏,可以用文件指纹验证(MD5)技术进行确认。
  原理:
  通过某种算法,对具体的文件进行校验,得出了一个32位的十六进制数(校验和)。待校验文件的文件名和后缀名都可以更改,不影响校核。由于原来的信息只要有稍许改动,通过md5运算后,结果都会有很大的改变。所以,如果再次校验以后所得到的值(md5代码)和此软件发布站或官方网站公布的值不同,就可以认为,文件已被改动过。
  需要注意的是,每个文件对应的MD5的值是不一样的,那么回归到本文主旨,当你使用一套完整的CMS系统的时候,下载了该CMS系统包含的CSS,字体,图标文件,这些文件中有些都是该CMS系统特有的,访问该文件如果该文件存在,然后校验该文件的MD5值,如果与指纹库中一致,则可以判断该网站的CMS类型,该方法相对前面准确率较高。
  指纹库格式是这样:
  网站文件|CMS类型|网站文件的MD5值。<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/static/image/admincp/cloud/qun_op.png|DISCUZ|AB35FA459B0BB01D31BA8FAD0953FCC9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/widget/images/thumbnail.jpg|ECSHOP|7BB50E4281FA02758834A2E9D7BA9FB9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/js/calendar/active-bg.gif|ECSHOP|F8FB9F2B7428C94B41320AA1BC9CF601|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/phpcms/libs/data/font/Vineta.ttf|PHPCMS|E6E557BAD69B09533827D9652E0C11AB|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/statics/images/admin_img/arrowhead-y.png|PHPCMS|6C34F70BD2A05C8C5DDEBB369B5B9509|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  即网站加上网站文件的网址,获取该文件的MD5值,对照指纹库的值是否一致,如果一致则确认该网站使用的CMS类型。python实现识别方式使用代码实现也就四五行,我们假设案例,假设一个指纹库:
  upload/my_girl.jpg|HEXO|587c7132e6043a1de24e03ededa8980d<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  然后使用代码实践进行识别:
  import hashlib,requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />URL = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />req = requests.get(url=URL+'/upload/my_girl.jpg')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5.update(req.content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if md5.hexdigest() == '587c7132e6043a1de24e03ededa8980d':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print('目标网址CMS类型为:HEXO')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试代码结果如下:
  
  根据指定网页内容识别CMS类型
  此类方法结合了上面几种情况下的指纹库,即CMS系统中默认包含一些网页或者文本,这些文本在你搭建好系统后任然存在,你访问这些网页或者文本,然后查看网页文本中是否存在特定的关键词,如果存在就确认CMS类型。
  如下文目标网址使用EmpireCMS(帝国网站管理系统)搭建,访问该网站的:
  e/admin/adminstyle/1/page/about.htm<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  文件,发现该页面存在,然后命中关键词,得出结果该网址使用的帝国网站管理系统搭建而成。
  字典中触发关键词识别,判定为帝国网址管理系统。
  
  补充说明
  除了上面五种访问不同文件类型,然后根据指纹库判定CMS类型,有些时候还可以通过访问错误页面获取信息,这时候可能会遇到防火墙阻拦。
  或者有些网站会对目录做一些修改,可以根据实际情况修改扫描代码,自定义添加二级目录扫描对照指纹库有时候也能发现很多敏感信息。
  上面五种方法中,按照准确率由高到低排序为:
  MD5值校验识别>指定网页内容识别>Robots.txt文件识别>请求头信息识别>首页内容识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  按照扫描需要的时间由低到高排序为:
  首页内容识别=请求头信息识别=Robots.txt文件识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  因为首页内容识别、请求头信息识别、Robots.txt文件识别只用访问一次该网站,不会产生大量的扫描,成功与否主要取决于你的指纹库。如果要扫描指定网页内容和校验MD5值,则会产生较多甚至大量的访问扫描,很容易触发防火墙引起很多麻烦事情上身,当然这些都可以通过降低扫描频率、自动随机切换代理IP、分布式低频率扫描等多种手段绕过。
  回归到本文主旨,识别CMS类型最最重要还得依赖强大的指纹库,甚至可以说完全依赖于指纹库的数据,五种方法只是思路的一个分类,能不能产出结果还是要靠指纹库的,关于如何更新整理指纹库,可以在GitHub上收集整理,各大论坛也有好心人专门整理,当然你也可以自己下载多套CMS系统,然后自己分析哪些文件是CMS独有的,校验出MD5值或者考察关键词等等清洗数据后加入更新到你的指纹库。
  Python识别CMS代码工程设计实现与拓展
  虽然整个工程看上去很多东西挺复杂,但是仔细去分析各个功能模块就会发现很容易实现,你需要做的就是把每个功能单独完成后,整体搭建在一起形成一套流程即可。下面演示代码为大致流程,方便阅读理解。
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  所以只需要访问一次网址的首页,拿到首页内容和请求头信息先对比,访问robots.txt文件检测,最后扫描指定网页内容检测关键词和验证MD5值。
  具体流程图:
  
  代码实现如下:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 指纹库信息,因为我收集了差不多5000条指纹,如果全部放在代码中,则文章就写不下了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 本代码仅作演示案例的工程结构<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 关于优化以及拓展,详细会在文章中介绍<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 首页内容指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 请求头信息指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># robots文件指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># MD5指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 特定网页指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 最后根据MD5值判定,其实如果前面都没有判定出来的话,这里扫描的意义也不是很大<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in cms_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_s = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_s)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5.update(res[1])<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            rmd5 = md5.hexdigest()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 == rmd5:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if __name__ == '__main__':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print(CheckCMS(url))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试结果:
  以上大致就是使用代码识别CMS类型的流程,有代码基础的同学可以自己进行拓展,举几个例子:
  加入WAF识别功能,即调用特定网页内容鉴定和MD5值校验之前,启动WAF识别,如果发现存在WAF就自行跳过,关于WAF识别的代码在公众号上两篇文章有源代码
  加入随机请求头,随机代理IP等条件,伪装成浏览器
  对网站的目录进行爬行,然后抓取爬行网页的内容对比参照指纹库关键词,有些时候也能命中不少,因为一些关键词不一定出现在首页,也有可能出现在错误页面或者404页面中
  引入线程池,实现批量扫描网址然后识别CMS类型后保存在文本,同样可以实现批量刷洞的效果,不过这种做法有涉及到HC的嫌疑,所以如果不是业务需求还是不要去做
  寻找多个在线识别CMS的接口,然后写个爬虫,结合在一起识别,当然这个如果作为长期使用的话,还得定期检查接口是否有效
  单单仅凭靠首页内容关键词判定CMS类型,其实是存在较大的误报率,可以结合robots文件等一起结合判断
  可以结合其他知识点做出有意思的东西,主要是要把自己的思维拓展开,比如结合Flask做一个简易版在线版识别CMS,也就十几行代码。一时手痒写一个,图个乐吧大家….
  代码如下:
  # coding:utf-8<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />from flask import Flask,request<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />app = Flask(__name__)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !

cms+php/oc,二次开发,网站设计模板

网站优化优采云 发表了文章 • 0 个评论 • 68 次浏览 • 2022-06-03 06:07 • 来自相关话题

  cms+php/oc,二次开发,网站设计模板
  cms网站后台内容管理系统模板开发,cms网站后台模板制作saas/cms培训/代码,数据库,工程开发网站功能区域划分图phpcms基础编程saas产品集成wap/seh5,app开发源码/模板/页面/模板,数据库,工程开发前端一键代码生成神马修phpcms,cms,cms网站二次开发/saas/cms产品开发,代码二次开发开源产品代码库提供给大家,节省了时间,增加了我们产品的价值,将来可以更方便大家。
  asp+php/oc/php,二次开发,网站设计模板推荐工具3c875ba817,3c875ba817二次开发是一个帮助网站开发者快速掌握各种小系统二次开发的实用工具箱提供开发效率,减少网站开发时间,减少维护工作量。还提供各种二次开发机制,云开发技术,等技术支持,方便大家开发出有价值的产品。工具箱功能区域划分图非常详细的工具箱图,大家根据需要自行对比筛选。
  phpcms源码下载、代码生成工具4loodway+simpleweb——仅需2分钟使用saas工具最为方便,节省的时间就是生命。代码模板化代码使用格式化的代码生成器生成,模板更加新颖。代码自动化开发全自动代码开发,按照我们写的代码生成器生成代码,变动维护非常方便,操作熟练后可以把自己生成的代码定制成一个自己专用的项目。
  大家可以自行体验,生成的代码一个是商城,一个是旅游。cms开发培训,cms网站后台模板制作,cms程序开发,cms开发的网站很多,很多网站会要求程序要有多少程序员,如果有很多人并没有做好开发工作,公司可能根本无法正常运转下去。很多公司是代码团队,但是项目开发周期又很紧迫,无法找到程序员帮助开发,这个时候往往会使用第三方的cms,如云开发,我们也不例外。
  5代码进度管理,phpcms多人开发开发进度管理phpcms自定义rd人员开发管理,rd员工进度管理。公司招聘也可以使用代码自动化开发。6代码文件管理,phpcms代码rd多代码。分批次编译代码,代码自动化生成。7存储系统自动化更新不用找人手动更新代码,自动化编译,自动化发布到各个存储系统如cvs/git/svn/metis/apowk等等自动化更新。
  自动化修改错误代码等自动化管理工具8开发质量管理多代码库,大部分程序不用重新编译。根据你的需求开发的多代码。结语:phpcms企业用户使用规范-4l。 查看全部

  cms+php/oc,二次开发,网站设计模板
  cms网站后台内容管理系统模板开发,cms网站后台模板制作saas/cms培训/代码,数据库,工程开发网站功能区域划分图phpcms基础编程saas产品集成wap/seh5,app开发源码/模板/页面/模板,数据库,工程开发前端一键代码生成神马修phpcms,cms,cms网站二次开发/saas/cms产品开发,代码二次开发开源产品代码库提供给大家,节省了时间,增加了我们产品的价值,将来可以更方便大家。
  asp+php/oc/php,二次开发,网站设计模板推荐工具3c875ba817,3c875ba817二次开发是一个帮助网站开发者快速掌握各种小系统二次开发的实用工具箱提供开发效率,减少网站开发时间,减少维护工作量。还提供各种二次开发机制,云开发技术,等技术支持,方便大家开发出有价值的产品。工具箱功能区域划分图非常详细的工具箱图,大家根据需要自行对比筛选。
  phpcms源码下载、代码生成工具4loodway+simpleweb——仅需2分钟使用saas工具最为方便,节省的时间就是生命。代码模板化代码使用格式化的代码生成器生成,模板更加新颖。代码自动化开发全自动代码开发,按照我们写的代码生成器生成代码,变动维护非常方便,操作熟练后可以把自己生成的代码定制成一个自己专用的项目。
  大家可以自行体验,生成的代码一个是商城,一个是旅游。cms开发培训,cms网站后台模板制作,cms程序开发,cms开发的网站很多,很多网站会要求程序要有多少程序员,如果有很多人并没有做好开发工作,公司可能根本无法正常运转下去。很多公司是代码团队,但是项目开发周期又很紧迫,无法找到程序员帮助开发,这个时候往往会使用第三方的cms,如云开发,我们也不例外。
  5代码进度管理,phpcms多人开发开发进度管理phpcms自定义rd人员开发管理,rd员工进度管理。公司招聘也可以使用代码自动化开发。6代码文件管理,phpcms代码rd多代码。分批次编译代码,代码自动化生成。7存储系统自动化更新不用找人手动更新代码,自动化编译,自动化发布到各个存储系统如cvs/git/svn/metis/apowk等等自动化更新。
  自动化修改错误代码等自动化管理工具8开发质量管理多代码库,大部分程序不用重新编译。根据你的需求开发的多代码。结语:phpcms企业用户使用规范-4l。

自定义用于 Web 开发的开源 PHP 框架 Codeigniter | Lin

网站优化优采云 发表了文章 • 0 个评论 • 104 次浏览 • 2022-05-31 21:29 • 来自相关话题

  自定义用于 Web 开发的开源 PHP 框架 Codeigniter | Lin
  译者:geekpi
  PHP Codeigniter 是一个开源框架,为商业应用提供易于使用的 PHP 编程语言和强大的编码工具。它还提供商务智能、服务器监视、开发和应用集成功能。这是一个相对冷清的项目,你很少听到它,但它功能强大,许多刚接触的开发人员都对此感到惊讶和耳目一新。
  我在新加坡的一家在线学习服务提供商处使用Codeigniter。我们提供的服务并不算常见,没有可以作为模板的默认功能集或现有后台管理系统,所以我需要一个能提供良好的、可靠的、可以建立在此基础上的原始材料。最初,我考虑用其他平台(如 Wordpress)用于我们的网站。但是,我决定使用 Codeigniter,因为它的灵活性,以及集成了在我们的补课匹配过程中需要的功能。
  以下是打动我使用 Codeigniter 的原因:
  ◈与 MySQL 数据库的集成 —— 主要功能是允许客户端浏览导师的数据库并添加导师,例如类似于电子商务平台的“购物车”。◈客户端界面系统 —— 用户可以登录来管理偏好并编辑详细信息,修改所教的科目、旅游的地区、手机号码、地址等。◈定制的管理员面板 —— 管理员可以使用定制的管理面板访问客户提交的资料,它与客户服务功能集成在一起,因此管理员可以单独跟进。◈付款系统 —— 管理面板带有与 Paypal 集成的发票和付款网关。◈ CMS 编辑器界面 —— 管理员能够编辑博客和文章中的文本和图像,以及添加新页面。
  该项目花费了大约六个月的时间来完成,另外花了两个月的调试时间。如果我需要从头开始构建所有,或者尝试重新设计现有的框架以满足我们的需求,那将花费更长的时间,而且可能最终无法满足客户需求。
  
  功能和优点
  PHP Codeigniter还有很多吸引开发者的功能,包括错误处理和代码格式化,这些功能在各种编码情景下都非常有用。它支持模板,可用于向现有网站添加功能或生成新网站。有许多基于 web 系统商业需要的功能,包括使用自定义标签。即使没有编程经验的普通开发人员也可以使用大多数工具。
  Codeigniter 的主要功能是:
  ◈XML 核心服务,◈HTTP/FTP 核心服务◈AppData 和 PHP 沙箱功能◈XSLT 和 HTML 模板◈加密的信息传输◈PCM Codeigniter 服务器监控◈应用集成◈文件传输协议(FTP)◈服务台支持◈Apache POI(用于托管网站的内容管理基础架构)
  
  兼容性
  Codeigniter 与许多领先的软件程序兼容,例如 PHP、MySQL、MariaDB、phpMyAdmin、Apache、OpenBSD、XSLT、SQLite等。许多公司更喜欢使用 Codeigniter 产品来满足网站要求,因为它们易于使用和集成。如果你不想创建自己的网站,你可以找到许多提供自定义 Web 开发服务的开发人员和设计机构。
  
  安全
  Codeigniter 还通过 SSL 加密提供数据安全性。加密可以保护数据免受入侵者和防火墙外部威胁的侵害。数据存储功能还允许对公司网站进行安全审核。
  
  其它功能
  一家优秀的 PHP Web 开发公司会使用几种高级技术和第三方技术,例如 XML 和 PHP。它为企业提供了一个完整的平台,可以开发出具有看起来专业的、好用的商业网站。Codeigniter 使得第三方技术的使用变得容易,并可以与常见的 Web 开发软件一起使用。这使得 Web 公司可以轻松地使用所选模块创建网站。大多数 PHP 开发者也为个人提供支持和培训服务。
  
  使用 PHP 框架 Codeigniter
  Codeigniter 给企业提供了完整的 PHP 开发包,它将提供强大的功能、灵活性和性能完美结合在一起。到目前为止,我很满意我们的网站,并不断地升级和添加新的功能。并不断升级和增加新的功能。我期待着发现我们的网站还能用 Codeigniter 做些什么。你也是这样么?
  via:
  作者:Wee Ben Sen选题:lujun9972译者:geekpi校对:wxy
  本文由LCTT原创编译,Linux中国荣誉推出
   查看全部

  自定义用于 Web 开发的开源 PHP 框架 Codeigniter | Lin
  译者:geekpi
  PHP Codeigniter 是一个开源框架,为商业应用提供易于使用的 PHP 编程语言和强大的编码工具。它还提供商务智能、服务器监视、开发和应用集成功能。这是一个相对冷清的项目,你很少听到它,但它功能强大,许多刚接触的开发人员都对此感到惊讶和耳目一新。
  我在新加坡的一家在线学习服务提供商处使用Codeigniter。我们提供的服务并不算常见,没有可以作为模板的默认功能集或现有后台管理系统,所以我需要一个能提供良好的、可靠的、可以建立在此基础上的原始材料。最初,我考虑用其他平台(如 Wordpress)用于我们的网站。但是,我决定使用 Codeigniter,因为它的灵活性,以及集成了在我们的补课匹配过程中需要的功能。
  以下是打动我使用 Codeigniter 的原因:
  ◈与 MySQL 数据库的集成 —— 主要功能是允许客户端浏览导师的数据库并添加导师,例如类似于电子商务平台的“购物车”。◈客户端界面系统 —— 用户可以登录来管理偏好并编辑详细信息,修改所教的科目、旅游的地区、手机号码、地址等。◈定制的管理员面板 —— 管理员可以使用定制的管理面板访问客户提交的资料,它与客户服务功能集成在一起,因此管理员可以单独跟进。◈付款系统 —— 管理面板带有与 Paypal 集成的发票和付款网关。◈ CMS 编辑器界面 —— 管理员能够编辑博客和文章中的文本和图像,以及添加新页面。
  该项目花费了大约六个月的时间来完成,另外花了两个月的调试时间。如果我需要从头开始构建所有,或者尝试重新设计现有的框架以满足我们的需求,那将花费更长的时间,而且可能最终无法满足客户需求。
  
  功能和优点
  PHP Codeigniter还有很多吸引开发者的功能,包括错误处理和代码格式化,这些功能在各种编码情景下都非常有用。它支持模板,可用于向现有网站添加功能或生成新网站。有许多基于 web 系统商业需要的功能,包括使用自定义标签。即使没有编程经验的普通开发人员也可以使用大多数工具。
  Codeigniter 的主要功能是:
  ◈XML 核心服务,◈HTTP/FTP 核心服务◈AppData 和 PHP 沙箱功能◈XSLT 和 HTML 模板◈加密的信息传输◈PCM Codeigniter 服务器监控◈应用集成◈文件传输协议(FTP)◈服务台支持◈Apache POI(用于托管网站的内容管理基础架构)
  
  兼容性
  Codeigniter 与许多领先的软件程序兼容,例如 PHP、MySQL、MariaDB、phpMyAdmin、Apache、OpenBSD、XSLT、SQLite等。许多公司更喜欢使用 Codeigniter 产品来满足网站要求,因为它们易于使用和集成。如果你不想创建自己的网站,你可以找到许多提供自定义 Web 开发服务的开发人员和设计机构。
  
  安全
  Codeigniter 还通过 SSL 加密提供数据安全性。加密可以保护数据免受入侵者和防火墙外部威胁的侵害。数据存储功能还允许对公司网站进行安全审核。
  
  其它功能
  一家优秀的 PHP Web 开发公司会使用几种高级技术和第三方技术,例如 XML 和 PHP。它为企业提供了一个完整的平台,可以开发出具有看起来专业的、好用的商业网站。Codeigniter 使得第三方技术的使用变得容易,并可以与常见的 Web 开发软件一起使用。这使得 Web 公司可以轻松地使用所选模块创建网站。大多数 PHP 开发者也为个人提供支持和培训服务。
  
  使用 PHP 框架 Codeigniter
  Codeigniter 给企业提供了完整的 PHP 开发包,它将提供强大的功能、灵活性和性能完美结合在一起。到目前为止,我很满意我们的网站,并不断地升级和添加新的功能。并不断升级和增加新的功能。我期待着发现我们的网站还能用 Codeigniter 做些什么。你也是这样么?
  via:
  作者:Wee Ben Sen选题:lujun9972译者:geekpi校对:wxy
  本文由LCTT原创编译,Linux中国荣誉推出
  

cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶

网站优化优采云 发表了文章 • 0 个评论 • 91 次浏览 • 2022-05-30 10:00 • 来自相关话题

  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶
  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶2.常用主题介绍和参数详解3.特色功能介绍和拓展介绍4.使用方法整理和总结5.历史功能清单根据工具类型,
  cms,比如7k7k、uiwebshop、wp、pageadmin、wordpress、discuz等等这些都是不错的设计模板、程序主题、插件程序和模板。有兴趣的可以加下微信好友。
  这种网站可以实现做php版的啊,我这里做的一个npm版本的网站,当然也能用前端语言写,网站框架我没设计过,我用的db5和wordpress,网站来源于小程序搜索推荐,
  那些好用的开源php后台主题及使用方法
  cms后台都有后台模板,只要是php就能一键换框架,所以原则上没有比较好用的版本,同样都是php的话,用谁的,用前端开发的那个都能实现你要的功能。
  php后台程序+cms美化框架程序+扩展php后台程序只是最基本的内容,多数后台需要处理逻辑、还有反应时间,但这些功能都可以用cms框架开发。要注意框架的选择!如果没有考虑用户体验,用自己原来写的没有问题,但用框架开发的话,你可以为他重写整个模板,速度快,但以后有bug能修复吗?如果你们公司以后需要扩展功能,你可以为扩展重写整个框架,但后期有bug你能修复吗?以后扩展需要update那些数据库模块,你们知道维护吗?有时用户申请模版都返回不了,要重新重写mvc模式,没有这个功能就进不去,模版不稳定时,网站浏览器看起来是不稳定,查看不到。
  而模版稳定就直接满足要求。当然框架看上去好看,还有很多具体应用可以用,比如,你前端写一个类似的框架,一般带时下的主流框架,像uiwebshop这些,你可以带标签、带颜色等等,但你后台写的太好了,用户会觉得你有多套后台,使用了各种的插件程序,很烦,更可能用户使用不了。找个框架吧,方便事物也多,国内多数的框架大同小异,看哪个功能强大简单易用快速,你就用哪个。
  cms的应用,你需要有学习整个框架语言,图形化做外观界面,操作也有快捷键,能访问数据库等。视觉好看的框架是好,多一个功能也可以省事,设计好的页面功能丰富全,感觉不到有换了个版本,功能比较强大。然后每个网站不同,都有一些功能需要处理,对接不一样的外网,模板上也可以和外网访问联动,具体要看具体情况。你的功能要注意的。 查看全部

  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶
  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶2.常用主题介绍和参数详解3.特色功能介绍和拓展介绍4.使用方法整理和总结5.历史功能清单根据工具类型,
  cms,比如7k7k、uiwebshop、wp、pageadmin、wordpress、discuz等等这些都是不错的设计模板、程序主题、插件程序和模板。有兴趣的可以加下微信好友。
  这种网站可以实现做php版的啊,我这里做的一个npm版本的网站,当然也能用前端语言写,网站框架我没设计过,我用的db5和wordpress,网站来源于小程序搜索推荐,
  那些好用的开源php后台主题及使用方法
  cms后台都有后台模板,只要是php就能一键换框架,所以原则上没有比较好用的版本,同样都是php的话,用谁的,用前端开发的那个都能实现你要的功能。
  php后台程序+cms美化框架程序+扩展php后台程序只是最基本的内容,多数后台需要处理逻辑、还有反应时间,但这些功能都可以用cms框架开发。要注意框架的选择!如果没有考虑用户体验,用自己原来写的没有问题,但用框架开发的话,你可以为他重写整个模板,速度快,但以后有bug能修复吗?如果你们公司以后需要扩展功能,你可以为扩展重写整个框架,但后期有bug你能修复吗?以后扩展需要update那些数据库模块,你们知道维护吗?有时用户申请模版都返回不了,要重新重写mvc模式,没有这个功能就进不去,模版不稳定时,网站浏览器看起来是不稳定,查看不到。
  而模版稳定就直接满足要求。当然框架看上去好看,还有很多具体应用可以用,比如,你前端写一个类似的框架,一般带时下的主流框架,像uiwebshop这些,你可以带标签、带颜色等等,但你后台写的太好了,用户会觉得你有多套后台,使用了各种的插件程序,很烦,更可能用户使用不了。找个框架吧,方便事物也多,国内多数的框架大同小异,看哪个功能强大简单易用快速,你就用哪个。
  cms的应用,你需要有学习整个框架语言,图形化做外观界面,操作也有快捷键,能访问数据库等。视觉好看的框架是好,多一个功能也可以省事,设计好的页面功能丰富全,感觉不到有换了个版本,功能比较强大。然后每个网站不同,都有一些功能需要处理,对接不一样的外网,模板上也可以和外网访问联动,具体要看具体情况。你的功能要注意的。

Repractise架构篇一: CMS的重构与演进

网站优化优采云 发表了文章 • 0 个评论 • 97 次浏览 • 2022-05-26 00:12 • 来自相关话题

  Repractise架构篇一: CMS的重构与演进
  架构师(JiaGouX)我们都是架构师!
  
  重构系统是一项非常具有挑战性的事情。通常来说,在我们的系统是第二个系统的时候才需要重构,即这个系统本身已经很臃肿。我们花费了太量的时间在代码间的逻辑,开发新的功能变得越来越慢。这不仅仅可能只是因为我们之前的架构没有设计好,而且在我们开发的过程中没有保持着原先设计时的一些原则。如果是这样的情况,那么这就是一个复杂的过程。
  还有一种情况是我们发现了一种更符合我们当前业务的框架。
  动态CMSCMS简介
  CMS是Content Management System的缩写,意为"内容管理系统".它可以做很多的事情,但是总的来说就是Page和Blog——即我们要创建一些页面可以用于写一些About US、Contact Me,以及持续更新的博客或者新闻,以及其他子系统——通常更新不活跃。通过对这些博客或者新闻进行分类,我们就可以有不同的信息内容,如下图:
  
  CMS是政府和企业都需要的系统,他们有很多的信息需要公开,并且需要对其组织进行宣传。在我有限的CMS交付经验里(大学时期),一般第一次交付CMS的时候,已经创建了大部分页面。有时候这些页面可能直接存储在数据库中,后来发现这不是一个好的方案,于是很多页面变成了静态页面。随后,在CMS的生命周期里就是更新内容。
  因而,CMS中起其主导的东西还是Content,即内容。而内容是一些持续可变的东西。这也就是为什么WordPress这么流行于CMS界,它是一个博客系统,但是多数时候我们只需要更新内容。除此不得不提及的一个CMS框架是Drupal,两者一对比会发现Drupal比较强大。通常来说,强大的一个负作用就是——复杂。
  WordPress和Drupal这一类的系统都属于发布系统,而其后台可以称为编辑系统。
  一般来说CMS有下面的特点:
  CMS一直就是这样一个紧耦合的系统。
  CMS架构与Django
  说起来,我一直是一个CMS党。主要原因还在于我可以随心所欲地去修改网站的内容,修改网站的架构。好的CMS总的来说都有其架构图,下图似乎是Drupal的模块图
  
  一般来说,其底层都会有:
  我一直在使用一个名为Django的Python Web框架,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。它是一个MTV框架——与多数的框架并没有太大的区别。
  层次职责
  模型(Model),即数据存取层
  处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  模板(Template),即表现层
  处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  视图(View),即业务逻辑层
  存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。
  从框架本身来上看它和别的系统没有太大的区别。
  
  但是如果我们已经有多外模块(即Django中app的概念),那么系统的架构就有所不同了。
  
  这就是为何我喜欢用这个CMS的原因了,我的每个子系统都以APP的形式提供服务——博客是一个app,sitemap是一个app,api是一个app。系统直接解耦为类似于混合服务的架构,即不像微服务一样多语言化,又不会有宏应用的紧耦合问题。
  编辑-发布分离
  我们的编辑和发布系统在某种意义上紧耦合在一起了,当用户访问量特别大的时候,这样会让我们的应用变得特定慢。有时候编辑甚至发布不了新的东西,如下图引示:
  
  或者你认识出了上图是源自Martin Folwer的编辑-发布分离
  编辑-发布分离是几年前解耦复杂系统游来开来带来的一个成果。今天这个似乎已经很常见了,编辑的时候是在后台进行的,等到发布的时候已经变成了一个静态的HTML。
  已经有足够多的CMS支持这样的特性,运行起来似乎特别不错,当然这样的系统也会有缓存的问题。有了APP这后,这个趋势就更加明显了——人们需要提供一个API。到底是在现有的系统里提供一个新的API,还是创建一个新的API。
  这时候,我更愿意选择后者——毕竟紧耦合一个系统总会在后期带来足够多的麻烦。而且基于数据库构建一个只读的RESTful API并不是一个复杂的过程,而且也危险。这时候的瓶颈就是数据库,但是似乎数据库都是多数系统的瓶颈。人们想出了各种各样的技术来解决这个瓶颈。
  于是之前我试着用Node.js + RESTify将我的博客重构成了一个SPA,当然这个时候CMS还在运行着。出于SEO的原因我并没有在最后采用这个方案,因为我网站的主要流量来源是Google和是百度。但是我在另外的网站里混合了SPA与MPA,其中的性能与应用是相当的,除了第一次加载页面的时候会带来一些延时。
  除了Node.js + RESTify,也试了试Python + Falcon(一个高性能的RESTful框架)。这个API理论上也应该可以给APP直接使用,并且可以直接拿来生成静态页面。
  编辑-发布-开发分离:静态站点生成
  如React一样解决DOM性能的问题就是跳过DOM这个坑,要跳过动态网站的性能问题就是让网站变成静态。
  越来越多的开发人员开始在使用Github Pages作为他们的博客,这是一个很有意思的转变。主要的原因是这是免费的,并且基本上可以保证24x7小时是可用的——当且仅当Github发现故障的时候才会不可访问。
  在这一类静态站点生成器(Github)里面,比较流行的有下面的内容(数据来源: ):
  Jekyll / OctoPress。Jekyll和OctoPress是最流行的静态博客系统。
  Hexo。Hexo是NodeJS编写的静态博客系统,其生成速度快,主题数量相对也比较丰富。是OctoPress的优秀替代者。
  Sculpin。Sculpin是PHP的静态站点系统。Hexo和Octopress专注于博客,而有时候我们的需求不仅仅是博客,而是有类似CMS的页面生成需求。Sculpin是一个泛用途的静态站点生成系统,在支持博客常见的分页、分类tag等同时,也能较好地支持非博客的一般页面生成。
  Hugo。Hugo是GO语言编写的静态站点系统。其生成速度快,且在较好支持博客和非博客内容的同时提供了比较完备的主题系统。无论是自己写主题还是套用别人的主题都比较顺手。
  通常这一类的工具里会有下面的内容:
  模板
  支持Markdown
  元数据
  如Hexo这样的框架甚至提供了一键部署的功能。
  在我们写了相关的代码之后,随后要做的就是生成HTML。对于个人博客来说,这是一个非常不错的系统,但是对于一些企业级的系统来说,我们的要求就更高了。如下图是Carrot采用的架构:
  
  这与我们在项目上的系统架构目前相似。作为一个博主,通常来说我们修改博客的主题的频率会比较低, 可能是半年一次。如果你经常修改博客的主题,你博客上的文章一定是相当的少。
  上图中的编辑者通过一个名为Contentful CMS来创建他们的内容,接着生成RESTful API。而类似的事情,我们也可以用Wordpress + RESTful 插件来完成。如果做得好,那么我想这个API也可以直接给APP使用。
  上图中的开发者需要不断地将修改的主题或者类似的东西PUSH到版本管理系统上,接着会有webhook监测到他们的变化,然后编译出新的静态页面。
  最后通过Netlify,他们编译到了一起,然后部署到生产环境。除了Netlify,你也可以编写生成脚本,然后用Bamboo、Go这类的CI工具进行编译。
  通常来说,生产环境可以使用CDN,如CloudFront服务。与动态网站相比,静态网站很容易直接部署到CDN,并可以直接从离用户近的本地缓存提供服务。除此,直接使用AWS S3的静态网站托管也是一个非常不错的选择。
  基于Github的编辑-发布-开发分离
  尽管我们已经在项目上实施了基于Github的部分内容管理已经有些日子里,但是由于找不到一些相关的资料,便不好透露相关的细节。直到我看到了《An Incremental Approach to Content Management Using Git 1》,我才意识到这似乎已经是一个成熟的技术了。看样子这项技术首先已经应用到了ThoughtWorks的官网上了。
  文中提到了使用这种架构的几个点:
  快速地开始项目,而不是学习或者配置框架。
  需要使用我们信奉的原则,如TDD。而这是大部分CMS所不支持的。
  基于服务的架构。
  灵活的语言和工具
  我们是开发人员。
  So,so,这些开发人员做了些什么:
  内容存储为静态文件
  不是所有的内容都是平等的
  引入内容服务
  使用Github。所有的content会提交到一个repo里,同时在我们push内容的时候,可以实时更新这些内容。
  允许内容通过内容服务更新
  使用Github API
  于是,有了一个名为Hacienda的框架用于管理内容,并存储为JSON。这意味着什么?
  
  因为使用了Git,我们可以了解到一个文件内容的历史版本,相比于WordPress来说更直观,而且更容易 上手。
  开发人员修改完他们的代码后,就可以直接提交,不会影响到Editor使用网站。Editor通过一个编辑器添加内容,在保存后,内容以JSON的形式出现直接提交代码到Github上相应的代码库中。CI或者Builder监测到他们的办法,就会生成新的静态页面。在这时候,我们可以选择有一个预览的平台,并且可以一键部署。那么,事情似乎就完成得差不多了。
  如果我们有APP,那么我们就可以使用Content Servies来做这些事情。甚至可以直接拿其搭建一个SPA。
  如果我们需要全文搜索功能,也变得很简单。我们已经不需要直接和数据库交互,我们可以直接读取JSON并且构建索引。这时候需要一个简单的Web服务,而且这个服务还是只读的。
  在需要的时候,如手机APP,我们可以通过Content Servies来创建博客。
  Repractise
  思考完这些后,我想到了一个符合学习的场景。
  
  我们构建的核心都可以基于Travis CI来完成,唯一存在风险的环节是我们似乎需要暴露我们的Key。
  其他
  参考文章:
  静态网站生成器将会成为下一个大热门
  EditingPublishingSeparation
  An Incremental Approach to Content Management Using Git 1
  Part 2: Implementing Content Management and Publication Using Git 查看全部

  Repractise架构篇一: CMS的重构与演进
  架构师(JiaGouX)我们都是架构师!
  
  重构系统是一项非常具有挑战性的事情。通常来说,在我们的系统是第二个系统的时候才需要重构,即这个系统本身已经很臃肿。我们花费了太量的时间在代码间的逻辑,开发新的功能变得越来越慢。这不仅仅可能只是因为我们之前的架构没有设计好,而且在我们开发的过程中没有保持着原先设计时的一些原则。如果是这样的情况,那么这就是一个复杂的过程。
  还有一种情况是我们发现了一种更符合我们当前业务的框架。
  动态CMSCMS简介
  CMS是Content Management System的缩写,意为"内容管理系统".它可以做很多的事情,但是总的来说就是Page和Blog——即我们要创建一些页面可以用于写一些About US、Contact Me,以及持续更新的博客或者新闻,以及其他子系统——通常更新不活跃。通过对这些博客或者新闻进行分类,我们就可以有不同的信息内容,如下图:
  
  CMS是政府和企业都需要的系统,他们有很多的信息需要公开,并且需要对其组织进行宣传。在我有限的CMS交付经验里(大学时期),一般第一次交付CMS的时候,已经创建了大部分页面。有时候这些页面可能直接存储在数据库中,后来发现这不是一个好的方案,于是很多页面变成了静态页面。随后,在CMS的生命周期里就是更新内容。
  因而,CMS中起其主导的东西还是Content,即内容。而内容是一些持续可变的东西。这也就是为什么WordPress这么流行于CMS界,它是一个博客系统,但是多数时候我们只需要更新内容。除此不得不提及的一个CMS框架是Drupal,两者一对比会发现Drupal比较强大。通常来说,强大的一个负作用就是——复杂。
  WordPress和Drupal这一类的系统都属于发布系统,而其后台可以称为编辑系统。
  一般来说CMS有下面的特点:
  CMS一直就是这样一个紧耦合的系统。
  CMS架构与Django
  说起来,我一直是一个CMS党。主要原因还在于我可以随心所欲地去修改网站的内容,修改网站的架构。好的CMS总的来说都有其架构图,下图似乎是Drupal的模块图
  
  一般来说,其底层都会有:
  我一直在使用一个名为Django的Python Web框架,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。它是一个MTV框架——与多数的框架并没有太大的区别。
  层次职责
  模型(Model),即数据存取层
  处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  模板(Template),即表现层
  处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  视图(View),即业务逻辑层
  存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。
  从框架本身来上看它和别的系统没有太大的区别。
  
  但是如果我们已经有多外模块(即Django中app的概念),那么系统的架构就有所不同了。
  
  这就是为何我喜欢用这个CMS的原因了,我的每个子系统都以APP的形式提供服务——博客是一个app,sitemap是一个app,api是一个app。系统直接解耦为类似于混合服务的架构,即不像微服务一样多语言化,又不会有宏应用的紧耦合问题。
  编辑-发布分离
  我们的编辑和发布系统在某种意义上紧耦合在一起了,当用户访问量特别大的时候,这样会让我们的应用变得特定慢。有时候编辑甚至发布不了新的东西,如下图引示:
  
  或者你认识出了上图是源自Martin Folwer的编辑-发布分离
  编辑-发布分离是几年前解耦复杂系统游来开来带来的一个成果。今天这个似乎已经很常见了,编辑的时候是在后台进行的,等到发布的时候已经变成了一个静态的HTML。
  已经有足够多的CMS支持这样的特性,运行起来似乎特别不错,当然这样的系统也会有缓存的问题。有了APP这后,这个趋势就更加明显了——人们需要提供一个API。到底是在现有的系统里提供一个新的API,还是创建一个新的API。
  这时候,我更愿意选择后者——毕竟紧耦合一个系统总会在后期带来足够多的麻烦。而且基于数据库构建一个只读的RESTful API并不是一个复杂的过程,而且也危险。这时候的瓶颈就是数据库,但是似乎数据库都是多数系统的瓶颈。人们想出了各种各样的技术来解决这个瓶颈。
  于是之前我试着用Node.js + RESTify将我的博客重构成了一个SPA,当然这个时候CMS还在运行着。出于SEO的原因我并没有在最后采用这个方案,因为我网站的主要流量来源是Google和是百度。但是我在另外的网站里混合了SPA与MPA,其中的性能与应用是相当的,除了第一次加载页面的时候会带来一些延时。
  除了Node.js + RESTify,也试了试Python + Falcon(一个高性能的RESTful框架)。这个API理论上也应该可以给APP直接使用,并且可以直接拿来生成静态页面。
  编辑-发布-开发分离:静态站点生成
  如React一样解决DOM性能的问题就是跳过DOM这个坑,要跳过动态网站的性能问题就是让网站变成静态。
  越来越多的开发人员开始在使用Github Pages作为他们的博客,这是一个很有意思的转变。主要的原因是这是免费的,并且基本上可以保证24x7小时是可用的——当且仅当Github发现故障的时候才会不可访问。
  在这一类静态站点生成器(Github)里面,比较流行的有下面的内容(数据来源: ):
  Jekyll / OctoPress。Jekyll和OctoPress是最流行的静态博客系统。
  Hexo。Hexo是NodeJS编写的静态博客系统,其生成速度快,主题数量相对也比较丰富。是OctoPress的优秀替代者。
  Sculpin。Sculpin是PHP的静态站点系统。Hexo和Octopress专注于博客,而有时候我们的需求不仅仅是博客,而是有类似CMS的页面生成需求。Sculpin是一个泛用途的静态站点生成系统,在支持博客常见的分页、分类tag等同时,也能较好地支持非博客的一般页面生成。
  Hugo。Hugo是GO语言编写的静态站点系统。其生成速度快,且在较好支持博客和非博客内容的同时提供了比较完备的主题系统。无论是自己写主题还是套用别人的主题都比较顺手。
  通常这一类的工具里会有下面的内容:
  模板
  支持Markdown
  元数据
  如Hexo这样的框架甚至提供了一键部署的功能。
  在我们写了相关的代码之后,随后要做的就是生成HTML。对于个人博客来说,这是一个非常不错的系统,但是对于一些企业级的系统来说,我们的要求就更高了。如下图是Carrot采用的架构:
  
  这与我们在项目上的系统架构目前相似。作为一个博主,通常来说我们修改博客的主题的频率会比较低, 可能是半年一次。如果你经常修改博客的主题,你博客上的文章一定是相当的少。
  上图中的编辑者通过一个名为Contentful CMS来创建他们的内容,接着生成RESTful API。而类似的事情,我们也可以用Wordpress + RESTful 插件来完成。如果做得好,那么我想这个API也可以直接给APP使用。
  上图中的开发者需要不断地将修改的主题或者类似的东西PUSH到版本管理系统上,接着会有webhook监测到他们的变化,然后编译出新的静态页面。
  最后通过Netlify,他们编译到了一起,然后部署到生产环境。除了Netlify,你也可以编写生成脚本,然后用Bamboo、Go这类的CI工具进行编译。
  通常来说,生产环境可以使用CDN,如CloudFront服务。与动态网站相比,静态网站很容易直接部署到CDN,并可以直接从离用户近的本地缓存提供服务。除此,直接使用AWS S3的静态网站托管也是一个非常不错的选择。
  基于Github的编辑-发布-开发分离
  尽管我们已经在项目上实施了基于Github的部分内容管理已经有些日子里,但是由于找不到一些相关的资料,便不好透露相关的细节。直到我看到了《An Incremental Approach to Content Management Using Git 1》,我才意识到这似乎已经是一个成熟的技术了。看样子这项技术首先已经应用到了ThoughtWorks的官网上了。
  文中提到了使用这种架构的几个点:
  快速地开始项目,而不是学习或者配置框架。
  需要使用我们信奉的原则,如TDD。而这是大部分CMS所不支持的。
  基于服务的架构。
  灵活的语言和工具
  我们是开发人员。
  So,so,这些开发人员做了些什么:
  内容存储为静态文件
  不是所有的内容都是平等的
  引入内容服务
  使用Github。所有的content会提交到一个repo里,同时在我们push内容的时候,可以实时更新这些内容。
  允许内容通过内容服务更新
  使用Github API
  于是,有了一个名为Hacienda的框架用于管理内容,并存储为JSON。这意味着什么?
  
  因为使用了Git,我们可以了解到一个文件内容的历史版本,相比于WordPress来说更直观,而且更容易 上手。
  开发人员修改完他们的代码后,就可以直接提交,不会影响到Editor使用网站。Editor通过一个编辑器添加内容,在保存后,内容以JSON的形式出现直接提交代码到Github上相应的代码库中。CI或者Builder监测到他们的办法,就会生成新的静态页面。在这时候,我们可以选择有一个预览的平台,并且可以一键部署。那么,事情似乎就完成得差不多了。
  如果我们有APP,那么我们就可以使用Content Servies来做这些事情。甚至可以直接拿其搭建一个SPA。
  如果我们需要全文搜索功能,也变得很简单。我们已经不需要直接和数据库交互,我们可以直接读取JSON并且构建索引。这时候需要一个简单的Web服务,而且这个服务还是只读的。
  在需要的时候,如手机APP,我们可以通过Content Servies来创建博客。
  Repractise
  思考完这些后,我想到了一个符合学习的场景。
  
  我们构建的核心都可以基于Travis CI来完成,唯一存在风险的环节是我们似乎需要暴露我们的Key。
  其他
  参考文章:
  静态网站生成器将会成为下一个大热门
  EditingPublishingSeparation
  An Incremental Approach to Content Management Using Git 1
  Part 2: Implementing Content Management and Publication Using Git

CloudBase CMS + Next.js:轻松构建一个内容丰富的站点

网站优化优采云 发表了文章 • 0 个评论 • 170 次浏览 • 2022-05-24 04:14 • 来自相关话题

  CloudBase CMS + Next.js:轻松构建一个内容丰富的站点
  项目背景试想一下,如果你现在要为你自己或者你所在的组织创建一个强内容的站点,同时要求好的 SEO(搜素引擎优化),比如博客,你会怎么做呢?
  由 vite 或者 create-react-app 等脚手架构建的普通 SPA 应用是不行的,因为这样数据都是通过 AJAX 返回的。你暂时不了解这些概念也没关系,你只需要知道,这种方式下,搜索引擎是无法很好地了解你的网站是干什么的,所以就算大众在搜索引擎搜索你的站点的相关内容,搜索引擎也很难把你的站点排在搜索结果前列。那么为每个页面都编写一个静态的 html 页面呢?比如,为每篇文章都编写一个 html 文件,然后放在服务器上,这样只要客户端请求某篇文章,服务器就把对应的文章页面直接返回。这样也不好,太麻烦了,如果每次更改内容,都要用硬编码的方式去应对,那就把事情弄得太复杂了。如果有一种后台系统,能让管理员通过后台系统的简单操作,就能修改网站呈现的内容就好了。
  
  SPA 应用
  
  纯粹静态网站开发本文就将带领你采用一种新颖的、便捷的开发方式——通过结合 CloudBase CMS 和 Next.js,去构建内容管理方便,利于 SEO 且响应快速的站点。CMS 是云开发 CloudBase 推出的一款无头(headless)内容管理系统,提供给开发者方便地管理内容资源的能力。所谓无头,意思就是内容管理系统只负责管理你的内容,比如文章内容和作者列表。这些内容可以在客户端或者服务端通过 SDK 或者 API 的方式去取得。而如何去展示这些内容,则由开发者自行全权掌控。Next.js 是一款生产级的 React 框架,它提供了静态生成的功能。静态生成的意思是,在构建的过程中,Next.js 就会自动执行数据拉取的逻辑,并把数据和 UI 渲染为一个个的静态 HTML 页面,这意味着,我们的站点将响应迅速,而且利于 SEO。
  
  本文将通过带领你构建一个个人博客,以展示如何结合这两者,并最终在腾讯云云开发上部署站点。Demo在线预览
  
  开启环境和项目1. 开通 CloudBase CMS首先,你要在腾讯云控制台开通你的第一个云开发环境。云开发环境是云开发中的一个概念,每个云环境都集成了应用开发需要的基础能力,比如云数据库、云函数,开发者可以方便地组合、使用它们,为应用开发赋能。TCB-CMS 也是建立在云环境之上的。创建环境时,你可以直接选择空模板并勾选免费资源选项即可,最后将环境命名为 my-blog。
  
  可以看到,环境已经在创建中了。环境创建完毕后,进入扩展应用模块,可以看到“CMS内容管理系统”,可以在这里安装它。设置都按照默认就可以了,唯一要注意的是,务必记住自己设置的管理员账号和密码。等安装完毕后,可以在已安装应用一栏中进入应用。点击访问地址后,我们可以直接访问应用。进入应用并输入管理员账号和密码,然后可以看到以下页面:
  
  现在,系统中还没有任何项目,点击创建一个名为 MyBlog 的新项目,创建完毕后进入项目,可以看到内容模型和内容集合,拿数据库作类比,这两者就是数据库表和数据库表内容的关系,这两者就是我们要设置和管理的内容。已经有准备好的数据可以直接导入,分别就在项目源码仓库中的 ./schema 和 ./data 文件夹中。点击导入按钮,然后选择导入文件即可。好了,现在 CMS 已经成功开通了,我们也往其中加入了内容。接下来,就可以着手 Next.js 应用的编写了。
  2. 启动 Next.js 项目Next.js 是构建于 React 之上的生产级前端框架。相比于原本的 React,Next.js 提供了静态生成、服务端渲染等特性,同时自带前端路由,我们这次就主要用到 Next.js 的静态生成功能。使用 Next.js 编写前端应用,和使用 create-react-app 脚手架编写 SPA 应用非常类似,而且更加便捷、开箱即用。直接在命令行执行以下命令可以创建 Next.js 的样板项目并启动它:
  npx create-next-app<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />npm run dev<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  访问 localhost:3000 可以看到以下效果:
  
  接下来,我们就将基于这个样板项目开发网站。首页这里,我们将在首页放置文章列表。首先,打开项目下的 ./pages/index.js,发现页面导出了一个函数式的 React 组件。在 Next.js 中,pages 目录下,除了 api 文件夹下的内容和 _app.js,其他每个 js 文件导出的 React 组件都对应着一个或者一种页面,并且由 Next.js 直接生成对应的路由,index.js 导出的函数式组件就直接对应着我们进入网站后的第一个页面,而其他 js 文件于 ./pages 的相对地址就是 Next.js 为其自动生成的路由。Next.js 在应用构建期,就会对每个页面执行数据拉取的逻辑,并根据 React 组件构建的 UI,渲染出最后的 HTML 页面,接下来,我们要做的就是,构建主页的 UI,以及为主页编写拉取数据的逻辑。UI 编写接下来对主页的 UI 进行修改:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Home({ posts }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 云开发小站<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Welcome to 云开发 CloudBase!<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {posts.map(post => (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {post.title} &rarr;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <p>{post.author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> ))}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}</p>
  可以看到,修改后的 Home 组件,接受了一个 posts 为参数,这个 post 就是文章列表数据,我们将它在组件中渲染出来。那么 post 从哪里来呢?在同一个 js 文件下,需要再导出一个 getStaticProps 函数。
  export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}
  这个函数返回的对象的 props 属性,就是导出的函数式组件用到的参数。所以,只需要在 getStaticProps 函数中得到数据并返回即可。拉取数据先安装拉取数据要用到的 SDK:
  npm install --save @cloudbase/node-sdk
  然后,我们再创建 env.js 文件,在其中填入云环境相关信息:
  export const tcbConfig = {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    env: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretId: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretKey: ''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中环境ID(env)可以直接在环境主页中看到,API 密钥(secretId,secretKey)则可以在访问管理中获取。最后,我们创建 ./lib/api.js,然后填入以下内容,将数据拉取的逻辑全部集中在这个文件中。
  import tcb from '@cloudbase/node-sdk';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { tcbConfig } from '../env';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const { Author, Article } = (() => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const db = tcb.init(tcbConfig).database();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Author: db.collection('author'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Article: db.collection('article'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />})();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getHomePosts = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const posts = (await Article<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({})<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .orderBy('_updateTime', 'desc')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .limit(10)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    for (const post of posts) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        const { name } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        posts<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  在 api.js 中,根据环境信息,对 SDK 进行了初始化,并创建了用于查询文章和作者的实例 Author 和 Ariticle。在 getHomePosts 函数中,我们获取了展示用的文章。具体的逻辑如果不懂也暂时不必深究,现在只需要知道:通过执行 getHomePosts 我们能从云环境的 CMS 系统中拉取文章列表。接着,再来修改 ./pages/index.js 文件:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getHomePosts } from '../lib/api'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: await getHomePosts()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,再访问 localhost:3000,可以看到如下效果:
  
  这标志着:我们成功从 CMS 中获取数据并能够渲染出静态页面来返回给客户端啦!文章页面接下来,就要着手编写文章页面了,基本流程差不多,但值得注意的是,文章页面和主页不同,只有一个主页,但是文章页面可能有无数个,而Next.js 提供了能力,能让我们只编写一个 js 文件,并加以细微的改动,就能渲染出无数的文章页面 。拉取用以渲染页面的文章内容先准备好需要的样式。首先创建 ./styles/Post.module.css 文件,具体样式内容可以参考:接着,创建 ./pages/post/[id].js 文件,这个文件对应的,就是路由形如 /post/{id} 的所有页面,而 id 的作用就是匹配文章的 _id。这样通过访问 URL:/post/{id1}.js,就能访问到文章id等于 id1 的文章对应页面。我们先往 [id].js 文件中填入以下的内容:
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Post({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> title,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> image,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> author,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> avator,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> contentHtml<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <img className={styles.image} src={image}></img><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 返回<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到,相比 index.js,[id].js 多出了一个 getStaticProps 函数,getStaticProps 也多了一个 parms 参数。getStaticProps 函数暂时不用管,而 param.id 就是在路由中匹配到的 id,可以借助它,执行获取对应文章内容的逻辑。在 api.js 中,添加以下内容:
  // 对于 image 类型的字段,直接取得的 id 需要转换为可用的 URL<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const dealWithUrl = url => 'https://' + url<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace(`cloud://${tcbConfig.env}.`, '')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace('/cloudbase-cms', '.tcb.qcloud.la/cloudbase-cms');<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getPost = async (id) => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const post = (await Article.where({ _id: id }).get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const { name, avator } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.avator = dealWithUrl(avator);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.image = dealWithUrl(post.image);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return post;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后安装 remark 以及 remark-html 两个库,我们将用它们把 markdown 转化为 html,然后修改 [id].js 文件中的 getStaticProps 为
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getPost } from '../../lib/api';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import remark from 'remark'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import html from 'remark-html'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const post = await getPost(params.id);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const processedContent = await remark()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .use(html)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .process(post.content)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> post.contentHtml = processedContent.toString()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: post<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  拉取所有的文章id以渲染所有文章页面只到这一步还不够,我们需要知道所有的路由可能匹配到的 id 值,Next.js 才能渲染出全部的文章页面。[id].js 多出的 getStaticPaths 函数正是用来返回 id 所有可能的匹配值的。这就是我们只需要编写一次拉取文章数据逻辑,编写一次文章页面 UI,就能让 Next.js 生成出无数文章的静态页面的奥秘。因为,可以让 Next.js 知道所有的文章 id,然后 Next.js 就能对每个文章页面执行一次生成了。修改往 api.js 中添加获取所有文章 id 的函数:
  export const getAllPostId = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    let posts = (await Article.where({}).get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return posts.map(value => ({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        params: { id: value._id }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后修改 getStaticPaths 函数:
  export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: await getAllPostId(),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,访问首页,随便进入一篇文章,就可以看到如下效果:
  
  到这里,我们就成功完成 Next.js 项目的构建啦!部署使用腾讯云云开发,你可以轻易地将应用部署到公共网络上。我们先修改 package.json 中依赖库的配置,因为云开发环境对于依赖版本有一定限制:
  "dependencies": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "@cloudbase/node-sdk": "^2.5.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "next": "9.5.4",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react-dom": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark": "^13.0.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark-html": "^13.0.1"<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,创建部署的配置文件 cloudbaserc.json,并填入以下内容:
  {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "envId": "{{env}}",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "version": "2.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "$schema": "https://framework-1258016615.t ... ot%3B,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functionRoot": "./functions",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functions": [],<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "region": "ap-shanghai",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "framework": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "name": "tcbcms-nextjs",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "plugins": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            "client": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "use": "@cloudbase/framework-plugin-next",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "inputs": {}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中的 env 换成你刚刚创建的云环境的 ID。修改完毕后,执行命令:
  cloudbase<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到部署流程启动,等待到部署完毕后,进入云环境的“我的应用”模块,会发现应用列表多了一个“tcbcms-nextjs”,点击访问键,就能访问刚刚创建的应用,而且是通过公网 IP,这说明我们的应用已经部署成功了。
  总结到此,我们的博客已经成功创建并部署了。以后如果博客中要添加新文章,或者要删改原有的文章,都只需要在 CMS 上进行内容的改动,然后在本地执行 Next.js 的构建和云开发部署即可。
  
  更多 Next.js 和云开发相关知识,可以查看官方文档:
  Next.js 官方文档:
  CloudBase CMS 官方文档:
  @cloudbase/node-sdk 官方文档:
  彩蛋:云开发是如何支撑应用开发的?你可能会好奇云环境的能力是如何支撑我们的系统的。再次进入腾讯云控制台,进入刚刚创建的云环境主页,进入HTTP访问服务、云数据库以及云函数模块,会发现多了许多东西。实际上,CMS 系统就是由这些东西支撑着的。我们每次访问 CMS 系统并操作,都会经由 HTTP访问服务,导向某个云函数,在云函数中执行后台逻辑,而系统中的数据,也都存储在云数据库中,这也是我们可以通过 @cloudbase/node-sdk 访问云数据库得到 CMS 中的数据的原因。而我们刚刚部署的 Next 应用,实际上也是运行在云函数上的。
  如果有兴趣在云开发中更进一步,欢迎前往云开发社区官网 阅读文档,加入,一起探索云开发的更多可能性。 查看全部

  CloudBase CMS + Next.js:轻松构建一个内容丰富的站点
  项目背景试想一下,如果你现在要为你自己或者你所在的组织创建一个强内容的站点,同时要求好的 SEO(搜素引擎优化),比如博客,你会怎么做呢?
  由 vite 或者 create-react-app 等脚手架构建的普通 SPA 应用是不行的,因为这样数据都是通过 AJAX 返回的。你暂时不了解这些概念也没关系,你只需要知道,这种方式下,搜索引擎是无法很好地了解你的网站是干什么的,所以就算大众在搜索引擎搜索你的站点的相关内容,搜索引擎也很难把你的站点排在搜索结果前列。那么为每个页面都编写一个静态的 html 页面呢?比如,为每篇文章都编写一个 html 文件,然后放在服务器上,这样只要客户端请求某篇文章,服务器就把对应的文章页面直接返回。这样也不好,太麻烦了,如果每次更改内容,都要用硬编码的方式去应对,那就把事情弄得太复杂了。如果有一种后台系统,能让管理员通过后台系统的简单操作,就能修改网站呈现的内容就好了。
  
  SPA 应用
  
  纯粹静态网站开发本文就将带领你采用一种新颖的、便捷的开发方式——通过结合 CloudBase CMS 和 Next.js,去构建内容管理方便,利于 SEO 且响应快速的站点。CMS 是云开发 CloudBase 推出的一款无头(headless)内容管理系统,提供给开发者方便地管理内容资源的能力。所谓无头,意思就是内容管理系统只负责管理你的内容,比如文章内容和作者列表。这些内容可以在客户端或者服务端通过 SDK 或者 API 的方式去取得。而如何去展示这些内容,则由开发者自行全权掌控。Next.js 是一款生产级的 React 框架,它提供了静态生成的功能。静态生成的意思是,在构建的过程中,Next.js 就会自动执行数据拉取的逻辑,并把数据和 UI 渲染为一个个的静态 HTML 页面,这意味着,我们的站点将响应迅速,而且利于 SEO。
  
  本文将通过带领你构建一个个人博客,以展示如何结合这两者,并最终在腾讯云云开发上部署站点。Demo在线预览
  
  开启环境和项目1. 开通 CloudBase CMS首先,你要在腾讯云控制台开通你的第一个云开发环境。云开发环境是云开发中的一个概念,每个云环境都集成了应用开发需要的基础能力,比如云数据库、云函数,开发者可以方便地组合、使用它们,为应用开发赋能。TCB-CMS 也是建立在云环境之上的。创建环境时,你可以直接选择空模板并勾选免费资源选项即可,最后将环境命名为 my-blog。
  
  可以看到,环境已经在创建中了。环境创建完毕后,进入扩展应用模块,可以看到“CMS内容管理系统”,可以在这里安装它。设置都按照默认就可以了,唯一要注意的是,务必记住自己设置的管理员账号和密码。等安装完毕后,可以在已安装应用一栏中进入应用。点击访问地址后,我们可以直接访问应用。进入应用并输入管理员账号和密码,然后可以看到以下页面:
  
  现在,系统中还没有任何项目,点击创建一个名为 MyBlog 的新项目,创建完毕后进入项目,可以看到内容模型和内容集合,拿数据库作类比,这两者就是数据库表和数据库表内容的关系,这两者就是我们要设置和管理的内容。已经有准备好的数据可以直接导入,分别就在项目源码仓库中的 ./schema 和 ./data 文件夹中。点击导入按钮,然后选择导入文件即可。好了,现在 CMS 已经成功开通了,我们也往其中加入了内容。接下来,就可以着手 Next.js 应用的编写了。
  2. 启动 Next.js 项目Next.js 是构建于 React 之上的生产级前端框架。相比于原本的 React,Next.js 提供了静态生成、服务端渲染等特性,同时自带前端路由,我们这次就主要用到 Next.js 的静态生成功能。使用 Next.js 编写前端应用,和使用 create-react-app 脚手架编写 SPA 应用非常类似,而且更加便捷、开箱即用。直接在命令行执行以下命令可以创建 Next.js 的样板项目并启动它:
  npx create-next-app<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />npm run dev<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  访问 localhost:3000 可以看到以下效果:
  
  接下来,我们就将基于这个样板项目开发网站。首页这里,我们将在首页放置文章列表。首先,打开项目下的 ./pages/index.js,发现页面导出了一个函数式的 React 组件。在 Next.js 中,pages 目录下,除了 api 文件夹下的内容和 _app.js,其他每个 js 文件导出的 React 组件都对应着一个或者一种页面,并且由 Next.js 直接生成对应的路由,index.js 导出的函数式组件就直接对应着我们进入网站后的第一个页面,而其他 js 文件于 ./pages 的相对地址就是 Next.js 为其自动生成的路由。Next.js 在应用构建期,就会对每个页面执行数据拉取的逻辑,并根据 React 组件构建的 UI,渲染出最后的 HTML 页面,接下来,我们要做的就是,构建主页的 UI,以及为主页编写拉取数据的逻辑。UI 编写接下来对主页的 UI 进行修改:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Home({ posts }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 云开发小站<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Welcome to 云开发 CloudBase!<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {posts.map(post => (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {post.title} &rarr;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <p>{post.author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> ))}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}</p>
  可以看到,修改后的 Home 组件,接受了一个 posts 为参数,这个 post 就是文章列表数据,我们将它在组件中渲染出来。那么 post 从哪里来呢?在同一个 js 文件下,需要再导出一个 getStaticProps 函数。
  export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}
  这个函数返回的对象的 props 属性,就是导出的函数式组件用到的参数。所以,只需要在 getStaticProps 函数中得到数据并返回即可。拉取数据先安装拉取数据要用到的 SDK:
  npm install --save @cloudbase/node-sdk
  然后,我们再创建 env.js 文件,在其中填入云环境相关信息:
  export const tcbConfig = {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    env: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretId: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretKey: ''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中环境ID(env)可以直接在环境主页中看到,API 密钥(secretId,secretKey)则可以在访问管理中获取。最后,我们创建 ./lib/api.js,然后填入以下内容,将数据拉取的逻辑全部集中在这个文件中。
  import tcb from '@cloudbase/node-sdk';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { tcbConfig } from '../env';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const { Author, Article } = (() => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const db = tcb.init(tcbConfig).database();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Author: db.collection('author'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Article: db.collection('article'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />})();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getHomePosts = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const posts = (await Article<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({})<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .orderBy('_updateTime', 'desc')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .limit(10)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    for (const post of posts) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        const { name } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        posts<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  在 api.js 中,根据环境信息,对 SDK 进行了初始化,并创建了用于查询文章和作者的实例 Author 和 Ariticle。在 getHomePosts 函数中,我们获取了展示用的文章。具体的逻辑如果不懂也暂时不必深究,现在只需要知道:通过执行 getHomePosts 我们能从云环境的 CMS 系统中拉取文章列表。接着,再来修改 ./pages/index.js 文件:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getHomePosts } from '../lib/api'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: await getHomePosts()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,再访问 localhost:3000,可以看到如下效果:
  
  这标志着:我们成功从 CMS 中获取数据并能够渲染出静态页面来返回给客户端啦!文章页面接下来,就要着手编写文章页面了,基本流程差不多,但值得注意的是,文章页面和主页不同,只有一个主页,但是文章页面可能有无数个,而Next.js 提供了能力,能让我们只编写一个 js 文件,并加以细微的改动,就能渲染出无数的文章页面 。拉取用以渲染页面的文章内容先准备好需要的样式。首先创建 ./styles/Post.module.css 文件,具体样式内容可以参考:接着,创建 ./pages/post/[id].js 文件,这个文件对应的,就是路由形如 /post/{id} 的所有页面,而 id 的作用就是匹配文章的 _id。这样通过访问 URL:/post/{id1}.js,就能访问到文章id等于 id1 的文章对应页面。我们先往 [id].js 文件中填入以下的内容:
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Post({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> title,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> image,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> author,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> avator,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> contentHtml<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <img className={styles.image} src={image}></img><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 返回<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到,相比 index.js,[id].js 多出了一个 getStaticProps 函数,getStaticProps 也多了一个 parms 参数。getStaticProps 函数暂时不用管,而 param.id 就是在路由中匹配到的 id,可以借助它,执行获取对应文章内容的逻辑。在 api.js 中,添加以下内容:
  // 对于 image 类型的字段,直接取得的 id 需要转换为可用的 URL<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const dealWithUrl = url => 'https://' + url<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace(`cloud://${tcbConfig.env}.`, '')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace('/cloudbase-cms', '.tcb.qcloud.la/cloudbase-cms');<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getPost = async (id) => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const post = (await Article.where({ _id: id }).get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const { name, avator } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.avator = dealWithUrl(avator);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.image = dealWithUrl(post.image);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return post;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后安装 remark 以及 remark-html 两个库,我们将用它们把 markdown 转化为 html,然后修改 [id].js 文件中的 getStaticProps 为
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getPost } from '../../lib/api';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import remark from 'remark'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import html from 'remark-html'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const post = await getPost(params.id);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const processedContent = await remark()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .use(html)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .process(post.content)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> post.contentHtml = processedContent.toString()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: post<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  拉取所有的文章id以渲染所有文章页面只到这一步还不够,我们需要知道所有的路由可能匹配到的 id 值,Next.js 才能渲染出全部的文章页面。[id].js 多出的 getStaticPaths 函数正是用来返回 id 所有可能的匹配值的。这就是我们只需要编写一次拉取文章数据逻辑,编写一次文章页面 UI,就能让 Next.js 生成出无数文章的静态页面的奥秘。因为,可以让 Next.js 知道所有的文章 id,然后 Next.js 就能对每个文章页面执行一次生成了。修改往 api.js 中添加获取所有文章 id 的函数:
  export const getAllPostId = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    let posts = (await Article.where({}).get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return posts.map(value => ({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        params: { id: value._id }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后修改 getStaticPaths 函数:
  export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: await getAllPostId(),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,访问首页,随便进入一篇文章,就可以看到如下效果:
  
  到这里,我们就成功完成 Next.js 项目的构建啦!部署使用腾讯云云开发,你可以轻易地将应用部署到公共网络上。我们先修改 package.json 中依赖库的配置,因为云开发环境对于依赖版本有一定限制:
  "dependencies": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "@cloudbase/node-sdk": "^2.5.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "next": "9.5.4",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react-dom": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark": "^13.0.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark-html": "^13.0.1"<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,创建部署的配置文件 cloudbaserc.json,并填入以下内容:
  {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "envId": "{{env}}",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "version": "2.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "$schema": "https://framework-1258016615.t ... ot%3B,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functionRoot": "./functions",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functions": [],<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "region": "ap-shanghai",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "framework": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "name": "tcbcms-nextjs",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "plugins": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            "client": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "use": "@cloudbase/framework-plugin-next",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "inputs": {}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中的 env 换成你刚刚创建的云环境的 ID。修改完毕后,执行命令:
  cloudbase<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到部署流程启动,等待到部署完毕后,进入云环境的“我的应用”模块,会发现应用列表多了一个“tcbcms-nextjs”,点击访问键,就能访问刚刚创建的应用,而且是通过公网 IP,这说明我们的应用已经部署成功了。
  总结到此,我们的博客已经成功创建并部署了。以后如果博客中要添加新文章,或者要删改原有的文章,都只需要在 CMS 上进行内容的改动,然后在本地执行 Next.js 的构建和云开发部署即可。
  
  更多 Next.js 和云开发相关知识,可以查看官方文档:
  Next.js 官方文档:
  CloudBase CMS 官方文档:
  @cloudbase/node-sdk 官方文档:
  彩蛋:云开发是如何支撑应用开发的?你可能会好奇云环境的能力是如何支撑我们的系统的。再次进入腾讯云控制台,进入刚刚创建的云环境主页,进入HTTP访问服务、云数据库以及云函数模块,会发现多了许多东西。实际上,CMS 系统就是由这些东西支撑着的。我们每次访问 CMS 系统并操作,都会经由 HTTP访问服务,导向某个云函数,在云函数中执行后台逻辑,而系统中的数据,也都存储在云数据库中,这也是我们可以通过 @cloudbase/node-sdk 访问云数据库得到 CMS 中的数据的原因。而我们刚刚部署的 Next 应用,实际上也是运行在云函数上的。
  如果有兴趣在云开发中更进一步,欢迎前往云开发社区官网 阅读文档,加入,一起探索云开发的更多可能性。

一款神仙儿宝藏级微服务开源项目,吊到炸裂!

网站优化优采云 发表了文章 • 0 个评论 • 79 次浏览 • 2022-05-23 10:52 • 来自相关话题

  一款神仙儿宝藏级微服务开源项目,吊到炸裂!
  大家好,我是Java架构师
  今天,推荐一个宝藏级微服务开源项目。我第一次使用就有点上头,爱不释手,必须要推荐给大家。
  上次是谁要的宝藏级微服务开源项目啊,我帮你找到了。
  这是我目前见过最好的宝藏级微服务开源项目。功能完整,代码结构清晰。值得推荐。 项目介绍
  前几天有粉丝留言,正在学习微服务,想让我推荐一个微服务学习项目。这次我拿出了压箱底的收藏了,一个宝藏级微服务开源项目,炸裂!
  前言
  zheng项目不仅仅是一个开发架构,而是努力打造一套从前端模板-基础框架-分布式架构-开源项目-持续集成-自动化部署-系统监测-无缝升级的全方位J2EE企业级开发解决方案。扩展:
  项目介绍
  基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公共微服务服务模块:内容管理、支付中心、用户管理(包括第三方)、微信平台、存储系统、配置中心、日志分析、任务和通知等,支持服务治理、监控和追踪,努力为中小型企业打造全方位J2EE企业级开发解决方案。
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!赶快收藏吧...</p>
  组织结构
  zheng<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-common -- SSM框架公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-admin -- 后台管理模板<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ui -- 前台thymeleaf模板[端口:1000]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-config -- 配置中心[端口:1001]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-upms -- 用户权限管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-common -- upms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-client -- 集成upms依赖包,提供单点认证、授权、统一会话管理<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-upms-server -- 用户权限系统及SSO服务端[端口:1111]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-cms -- 内容管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-common -- cms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-search -- 搜索服务[端口:2221]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-admin -- 后台管理[端口:2222]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-job -- 消息队列、任务调度等[端口:2223]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-cms-web -- 网站前台[端口:2224]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-pay -- 支付系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-common -- pay系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-admin -- 后台管理[端口:3331]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-pay-web -- 演示示例[端口:3332]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ucenter -- 用户系统(包括第三方登录)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-common -- ucenter系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-web -- 网站前台[端口:4441]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-wechat -- 微信系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-wechat-mp -- 微信公众号管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-service -- 业务逻辑<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    └── zheng-wechat-mp-admin -- 后台管理[端口:5551]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-app -- 微信小程序后台<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-api -- API接口总线系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-common -- api系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-api-server -- api系统服务端[端口:6666]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-oss -- 对象存储系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-web -- 前台接口[端口:7771]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-oss-admin -- 后台管理[端口:7772]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-message -- 实时通知系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-server -- 服务端[端口:8881,SocketIO端口:8882]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-message-client -- 客户端<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-shop -- 电子商务系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />└── zheng-demo -- 示例模块(包含一些示例代码等)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     └── zheng-demo-web -- 演示示例[端口:9999]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />
  架构图
  
  架构图模块依赖
  
  模块依赖环境搭建开发工具:开发环境:演示地址
  演示地址:[1]
  预览图
  
  
  
  数据模型
  
  数据库模型拓扑图
  
  拓扑图
  项目源码,怎么领取?
  
  源码获取
  
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!</p>
  扫码下方二维码,后台回复【宝藏】即可获取所有系统
  
  欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️<br mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="outline: 0px;line-height: 25.6px;" /><p data-tool="mdnice编辑器" mp-original-font-size="16" mp-original-line-height="28" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.544px;color: rgb(74, 74, 74);line-height: 28px;font-size: 16px;">在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!</p>
  最后,整理了300多套项目,赠送读者。扫码下方二维码,后台回复【赚钱】即可获取。
  <p style="text-align: center;"></p>
  --END-- 查看全部

  一款神仙儿宝藏级微服务开源项目,吊到炸裂!
  大家好,我是Java架构师
  今天,推荐一个宝藏级微服务开源项目。我第一次使用就有点上头,爱不释手,必须要推荐给大家。
  上次是谁要的宝藏级微服务开源项目啊,我帮你找到了。
  这是我目前见过最好的宝藏级微服务开源项目。功能完整,代码结构清晰。值得推荐。 项目介绍
  前几天有粉丝留言,正在学习微服务,想让我推荐一个微服务学习项目。这次我拿出了压箱底的收藏了,一个宝藏级微服务开源项目,炸裂!
  前言
  zheng项目不仅仅是一个开发架构,而是努力打造一套从前端模板-基础框架-分布式架构-开源项目-持续集成-自动化部署-系统监测-无缝升级的全方位J2EE企业级开发解决方案。扩展:
  项目介绍
  基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公共微服务服务模块:内容管理、支付中心、用户管理(包括第三方)、微信平台、存储系统、配置中心、日志分析、任务和通知等,支持服务治理、监控和追踪,努力为中小型企业打造全方位J2EE企业级开发解决方案。
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!赶快收藏吧...</p>
  组织结构
  zheng<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-common -- SSM框架公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-admin -- 后台管理模板<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ui -- 前台thymeleaf模板[端口:1000]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-config -- 配置中心[端口:1001]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-upms -- 用户权限管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-common -- upms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-client -- 集成upms依赖包,提供单点认证、授权、统一会话管理<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-upms-server -- 用户权限系统及SSO服务端[端口:1111]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-cms -- 内容管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-common -- cms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-search -- 搜索服务[端口:2221]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-admin -- 后台管理[端口:2222]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-job -- 消息队列、任务调度等[端口:2223]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-cms-web -- 网站前台[端口:2224]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-pay -- 支付系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-common -- pay系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-admin -- 后台管理[端口:3331]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-pay-web -- 演示示例[端口:3332]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ucenter -- 用户系统(包括第三方登录)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-common -- ucenter系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-web -- 网站前台[端口:4441]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-wechat -- 微信系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-wechat-mp -- 微信公众号管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-service -- 业务逻辑<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    └── zheng-wechat-mp-admin -- 后台管理[端口:5551]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-app -- 微信小程序后台<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-api -- API接口总线系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-common -- api系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-api-server -- api系统服务端[端口:6666]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-oss -- 对象存储系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-web -- 前台接口[端口:7771]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-oss-admin -- 后台管理[端口:7772]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-message -- 实时通知系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-server -- 服务端[端口:8881,SocketIO端口:8882]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-message-client -- 客户端<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-shop -- 电子商务系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />└── zheng-demo -- 示例模块(包含一些示例代码等)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     └── zheng-demo-web -- 演示示例[端口:9999]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />
  架构图
  
  架构图模块依赖
  
  模块依赖环境搭建开发工具:开发环境:演示地址
  演示地址:[1]
  预览图
  
  
  
  数据模型
  
  数据库模型拓扑图
  
  拓扑图
  项目源码,怎么领取?
  
  源码获取
  
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!</p>
  扫码下方二维码,后台回复【宝藏】即可获取所有系统
  
  欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️<br mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="outline: 0px;line-height: 25.6px;" /><p data-tool="mdnice编辑器" mp-original-font-size="16" mp-original-line-height="28" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.544px;color: rgb(74, 74, 74);line-height: 28px;font-size: 16px;">在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!</p>
  最后,整理了300多套项目,赠送读者。扫码下方二维码,后台回复【赚钱】即可获取。
  <p style="text-align: center;"></p>
  --END--

教程:cms网站后台内容管理系统模板更新:免费blog后台搭建

网站优化优采云 发表了文章 • 0 个评论 • 103 次浏览 • 2022-09-24 09:13 • 来自相关话题

  教程:cms网站后台内容管理系统模板更新:免费blog后台搭建
  cms网站后台内容管理系统模板更新:php下载地址:免费blog后台搭建课程:【工具】-传智播客-全网营销传播第一it教育平台
  免费的。我觉得最主要的是要看你是为了什么,如果是为了提高排名那确实还可以弄一个学院系统之类的。你要不想收费也可以。别的平台都需要登录。你不用怕。
  
  虽然是免费的。但是肯定会存在很多问题,花两三万弄不了什么东西。
  个人觉得,可以先买个域名,然后买个二级域名做起来。然后找一个免费的写一个网站就好了,别人可能花钱找你做你就说有点太贵了。
  
  目前来说,微型不收费的基本上都收费,收费的一般都不咋的,买大型的太贵,二三万也不便宜,买小型的又没安全感。实在不行花两三万买个四位数域名也是够的,然后注册一个空间。
  推荐使用优易云微型web2.0,这个web2.0平台免费注册,免费试用,体验成功可免费使用半年,使用免费开通后可开通更多功能。安全:一个人或几个人注册一个账号就可以实现服务器开通、免费部署和使用,不涉及独立的服务器,安全易控制。方便:运行安全可靠,网站访问方便,多人同时登录无负载。操作简单、使用方便。
  多人共享域名和网站内容。易于维护:免费发布,免费编辑,免费发布域名管理记录,域名备案,免费管理与维护网站内容。精准推送:根据自己的网站属性智能推送。可快速被访问到。便捷开通:支持邮箱注册,快速开通网站内容,快速管理网站。可以长期免费合作。 查看全部

  教程:cms网站后台内容管理系统模板更新:免费blog后台搭建
  cms网站后台内容管理系统模板更新:php下载地址:免费blog后台搭建课程:【工具】-传智播客-全网营销传播第一it教育平台
  免费的。我觉得最主要的是要看你是为了什么,如果是为了提高排名那确实还可以弄一个学院系统之类的。你要不想收费也可以。别的平台都需要登录。你不用怕。
  
  虽然是免费的。但是肯定会存在很多问题,花两三万弄不了什么东西。
  个人觉得,可以先买个域名,然后买个二级域名做起来。然后找一个免费的写一个网站就好了,别人可能花钱找你做你就说有点太贵了。
  
  目前来说,微型不收费的基本上都收费,收费的一般都不咋的,买大型的太贵,二三万也不便宜,买小型的又没安全感。实在不行花两三万买个四位数域名也是够的,然后注册一个空间。
  推荐使用优易云微型web2.0,这个web2.0平台免费注册,免费试用,体验成功可免费使用半年,使用免费开通后可开通更多功能。安全:一个人或几个人注册一个账号就可以实现服务器开通、免费部署和使用,不涉及独立的服务器,安全易控制。方便:运行安全可靠,网站访问方便,多人同时登录无负载。操作简单、使用方便。
  多人共享域名和网站内容。易于维护:免费发布,免费编辑,免费发布域名管理记录,域名备案,免费管理与维护网站内容。精准推送:根据自己的网站属性智能推送。可快速被访问到。便捷开通:支持邮箱注册,快速开通网站内容,快速管理网站。可以长期免费合作。

网站制作多少钱?

网站优化优采云 发表了文章 • 0 个评论 • 80 次浏览 • 2022-09-05 07:09 • 来自相关话题

  网站制作多少钱?
  php开源建站系统管家为企业和个人提供大量网页模板,网站模板,企业网站模板,我们还为用户提供了完整的CMS系统,cms内容管理系统,php开源建站系统,我们还承接web前端开发,php开发网站定制开发业务,为满足大部分客户需求,我们提供了上千种免费网页模板下载尽在php开源建站系统管家平台,如何网站模板无法满足你的需要可以联系php开源建站系统管家我们为你定制开发
  襄阳做网站公司有哪些?
  
  湖北速建时代网络科技有限公司,是一家专业做网站公司,主要业务:网站定制开发,网站设计制作,前后端开发,app开发,小程序开发,小程序商城开发,pc端商城开发等业务
  我们有成熟的网站后台和强大的网站模板库,便于用户选择,有多套建站方案供用户选择
  网站制作多少钱
  我们提供模板建站 100元起
  
  我们提供定制开发 3500元起
  我们提供前端定制开发 价格更功能待定价格
  我们承接前端外部业务 价格更功能待定价格
  我们承接小程序开发业务 价格更功能待定价格 查看全部

  网站制作多少钱?
  php开源建站系统管家为企业和个人提供大量网页模板,网站模板,企业网站模板,我们还为用户提供了完整的CMS系统,cms内容管理系统,php开源建站系统,我们还承接web前端开发,php开发网站定制开发业务,为满足大部分客户需求,我们提供了上千种免费网页模板下载尽在php开源建站系统管家平台,如何网站模板无法满足你的需要可以联系php开源建站系统管家我们为你定制开发
  襄阳做网站公司有哪些?
  
  湖北速建时代网络科技有限公司,是一家专业做网站公司,主要业务:网站定制开发,网站设计制作,前后端开发,app开发,小程序开发,小程序商城开发,pc端商城开发等业务
  我们有成熟的网站后台和强大的网站模板库,便于用户选择,有多套建站方案供用户选择
  网站制作多少钱
  我们提供模板建站 100元起
  
  我们提供定制开发 3500元起
  我们提供前端定制开发 价格更功能待定价格
  我们承接前端外部业务 价格更功能待定价格
  我们承接小程序开发业务 价格更功能待定价格

cms网站后台内容管理系统模板规格后台需求分析库存系统

网站优化优采云 发表了文章 • 0 个评论 • 120 次浏览 • 2022-09-04 21:05 • 来自相关话题

  cms网站后台内容管理系统模板规格后台需求分析库存系统
  cms网站后台内容管理系统模板规格后台需求分析库存系统计划系统购物车系统退换货管理系统收银系统营销系统活动系统导购系统财务系统销售系统seo系统
  后台一般都可以使用现成的,比如discuzcms,或者博客程序。前端最简单的是自己做,把后台整合进去,实现一套框架,然后把各项需求集成到框架上。一般都没有固定的模板,需要根据需求来。
  
  我目前知道的,都是外包给代理商,要看方案!例如先做网站公司,做好后台后,
  你可以上cms商用建站平台,上面的功能齐全,模板多,
  发布贴吧来看看有没有高手整理出来
  
  网上很多优秀的后台还是可以参考的,不过有些因为是按整站走的,
  国内外好多大的cms都可以利用系统自带模板套用做的,还是看需求,
  我们也做后台,我们通过项目经理推荐,公司里各部门推荐了几家开发公司。后来选了一家外包公司。网站程序还是要看需求。后台市场上好多都是现成的cms软件。如果你需要后台集成的功能,那么建议你直接找一个模板定制的开发公司比较好,因为从大的方面来说,开发公司制作产品容易,专业的就难了。一定要注意。这也看你需要网站的数据需要以何种形式导出。
  建议从收集了解对方建站产品与网站数据库的对接。前端易搭你可以考虑一下,我们在电商的代工工厂,然后专业做电商项目。总体来说后台开发也就那些。你需要后台很简单。 查看全部

  cms网站后台内容管理系统模板规格后台需求分析库存系统
  cms网站后台内容管理系统模板规格后台需求分析库存系统计划系统购物车系统退换货管理系统收银系统营销系统活动系统导购系统财务系统销售系统seo系统
  后台一般都可以使用现成的,比如discuzcms,或者博客程序。前端最简单的是自己做,把后台整合进去,实现一套框架,然后把各项需求集成到框架上。一般都没有固定的模板,需要根据需求来。
  
  我目前知道的,都是外包给代理商,要看方案!例如先做网站公司,做好后台后,
  你可以上cms商用建站平台,上面的功能齐全,模板多,
  发布贴吧来看看有没有高手整理出来
  
  网上很多优秀的后台还是可以参考的,不过有些因为是按整站走的,
  国内外好多大的cms都可以利用系统自带模板套用做的,还是看需求,
  我们也做后台,我们通过项目经理推荐,公司里各部门推荐了几家开发公司。后来选了一家外包公司。网站程序还是要看需求。后台市场上好多都是现成的cms软件。如果你需要后台集成的功能,那么建议你直接找一个模板定制的开发公司比较好,因为从大的方面来说,开发公司制作产品容易,专业的就难了。一定要注意。这也看你需要网站的数据需要以何种形式导出。
  建议从收集了解对方建站产品与网站数据库的对接。前端易搭你可以考虑一下,我们在电商的代工工厂,然后专业做电商项目。总体来说后台开发也就那些。你需要后台很简单。

cms网站后台内容管理系统模板(图):人人网

网站优化优采云 发表了文章 • 0 个评论 • 86 次浏览 • 2022-09-02 17:02 • 来自相关话题

  cms网站后台内容管理系统模板(图):人人网
  cms网站后台内容管理系统模板了解一下dz:人人网discuz:5655mcshop:?q=%e4%bf%be%e4%b8%88&aq=f&oq=%e4%bf%be%e4%b8%88&aqi=&aql=&aqlp=&by=&biw=1933&bih=2248建议用dz模板,前景还是很不错的;dz压力很小,性能还是挺不错的。其实用模板做建站是很有必要的,手写代码是很耗费精力的,建议用模板解决日常工作需要。
  
  mvc分层架构和springboot比较,关注点不同。
  如果是我的话,我选择用dz,因为这个模板非常好。这里推荐一下网站流量管理系统gweb而且压力也很小。如果是小公司的话我建议用dz(贵),做大了再搞springboot吧。大公司有成熟的开源技术模板也不错,使用的很多,你可以选择一个,什么时候都是拿来主义。
  
  就网站数据库存储来说,现在的网站数据库都可以支持各种标准化模板,这种方案不收学费,重点在于应用维护。一次建站,高维护成本。后期数据同步会成为问题。选择合适的建站工具是第一个挑战。数据库管理是长期的事情,急不得。人肉查询用google或者百度都可以。安全性,性能,维护性,
  wordpress、phpwind、dz都有模板和插件制作功能,可以从模板制作功能和插件制作功能去了解dz和phpwind,可以按目前的各自强项分别重点选择,根据模板制作和插件制作从而选择出最适合你的phpwind和dz,当然这样选择会麻烦一些,可以根据站点大小的接近作一些前期的准备。假如是phpwind和dz都不合适,那么就可以看下针对性内容、性能的phpmyadmin和dw这两款插件,再做做互联网收集的尝试。 查看全部

  cms网站后台内容管理系统模板(图):人人网
  cms网站后台内容管理系统模板了解一下dz:人人网discuz:5655mcshop:?q=%e4%bf%be%e4%b8%88&aq=f&oq=%e4%bf%be%e4%b8%88&aqi=&aql=&aqlp=&by=&biw=1933&bih=2248建议用dz模板,前景还是很不错的;dz压力很小,性能还是挺不错的。其实用模板做建站是很有必要的,手写代码是很耗费精力的,建议用模板解决日常工作需要。
  
  mvc分层架构和springboot比较,关注点不同。
  如果是我的话,我选择用dz,因为这个模板非常好。这里推荐一下网站流量管理系统gweb而且压力也很小。如果是小公司的话我建议用dz(贵),做大了再搞springboot吧。大公司有成熟的开源技术模板也不错,使用的很多,你可以选择一个,什么时候都是拿来主义。
  
  就网站数据库存储来说,现在的网站数据库都可以支持各种标准化模板,这种方案不收学费,重点在于应用维护。一次建站,高维护成本。后期数据同步会成为问题。选择合适的建站工具是第一个挑战。数据库管理是长期的事情,急不得。人肉查询用google或者百度都可以。安全性,性能,维护性,
  wordpress、phpwind、dz都有模板和插件制作功能,可以从模板制作功能和插件制作功能去了解dz和phpwind,可以按目前的各自强项分别重点选择,根据模板制作和插件制作从而选择出最适合你的phpwind和dz,当然这样选择会麻烦一些,可以根据站点大小的接近作一些前期的准备。假如是phpwind和dz都不合适,那么就可以看下针对性内容、性能的phpmyadmin和dw这两款插件,再做做互联网收集的尝试。

cms网站后台内容管理系统模板(图)官方介绍

网站优化优采云 发表了文章 • 0 个评论 • 98 次浏览 • 2022-08-21 22:02 • 来自相关话题

  cms网站后台内容管理系统模板(图)官方介绍
  cms网站后台内容管理系统模板目前总共四个系列,分别是martial型,redux型,grid型以及simulation型的。redux出了问题后,就推荐你一个微信小程序版,网站生成版也有,cms模板市场分别是eclipse,maven之类。使用markdown语法,后端php和nodejs都支持。redux和serviceworker网站服务器只要一台就行,nodejs即可。
  前端每个模板的布局包括图片风格都是我自己开发的。simulation系列基本全部用javascript实现,不一一细说。总之也都是实战中总结的。
  直接从网上搜有没有现成的
  
  最终效果如图
  推荐这个吧linkedin官方的!
  注册完需要进行简单的注册,同时你也需要填写一些基本的信息,然后到注册模板中心提交网站信息。注册模板中心可以选择一个开发者或者个人或者企业等,针对于个人或者企业进行创建,你也可以注册一个谷歌账号到谷歌商店里进行搜索。谷歌商店也是有的,不过不支持中文的版本,不知道网站是不是支持。其他的就不知道了。
  
  你登录网站后台就能找到了
  有微信小程序端,你登录后台就能找到了。
  有个链接,注册了那个账号,
  不知道你有没有注册成功注册成功链接/,貌似at&t这个网站有这个开发者登录的系统,你可以注册at&t的账号, 查看全部

  cms网站后台内容管理系统模板(图)官方介绍
  cms网站后台内容管理系统模板目前总共四个系列,分别是martial型,redux型,grid型以及simulation型的。redux出了问题后,就推荐你一个微信小程序版,网站生成版也有,cms模板市场分别是eclipse,maven之类。使用markdown语法,后端php和nodejs都支持。redux和serviceworker网站服务器只要一台就行,nodejs即可。
  前端每个模板的布局包括图片风格都是我自己开发的。simulation系列基本全部用javascript实现,不一一细说。总之也都是实战中总结的。
  直接从网上搜有没有现成的
  
  最终效果如图
  推荐这个吧linkedin官方的!
  注册完需要进行简单的注册,同时你也需要填写一些基本的信息,然后到注册模板中心提交网站信息。注册模板中心可以选择一个开发者或者个人或者企业等,针对于个人或者企业进行创建,你也可以注册一个谷歌账号到谷歌商店里进行搜索。谷歌商店也是有的,不过不支持中文的版本,不知道网站是不是支持。其他的就不知道了。
  
  你登录网站后台就能找到了
  有微信小程序端,你登录后台就能找到了。
  有个链接,注册了那个账号,
  不知道你有没有注册成功注册成功链接/,貌似at&t这个网站有这个开发者登录的系统,你可以注册at&t的账号,

企业网站的费用和流程一览

网站优化优采云 发表了文章 • 0 个评论 • 104 次浏览 • 2022-08-10 22:52 • 来自相关话题

  企业网站的费用和流程一览
  先说常规网站制作需要用到的东西:
  网站建设收费分三个部分 : 域名、服务器、源码(网站的设计制作)
  域名 :
  65元左右一个.com域名
  服务器 :
  企业展示型网站图片视频少,一般200元到300元左右的虚拟主机即可,如果需要承载大量宣传视频和高清案例图片,价格会贵一些。
  功能型网站,根据承载的业务量来选择服务器,价格从一千多到几千块上万不等。
  源码(网站的设计制作):
  企业/个人展示型网站一般300到500块钱。
  品牌型网站和营销型网站根据设计需要一般1000元起。
  功能型网站根据功能按需定制,价格一般一万起,开发周期正常都是最少三周起。(包含数据测试、压力测试、兼容性测试等等)。
  我们有多年稳定运行的建站软件平台,并且常年维护更新。快速帮助企业或个人完成网站搭建和上线。我们提供数千款精美网站素材和模板,且都是正版可商用,并提供云服务器和域名一键配置。快速帮助您建设制作高端大气商务网站和官方网站。
  
  您的担心:
  网站会不会被百度收录?
  内置一键提交百度收录,快速被百度收录。
  网站优化是不是很难做?
  内置配套SEO功能,只需要按提示设置关键词即可轻松优化整站和单页面搜索排名。即使不懂SEO也能轻松优化网站排名。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询
  随着互联网的发展,很多企业想要建立一个自己的企业网站,但是又苦于不懂技术,不清楚网站建设都有哪些费用和流程。下面跟大家科普一下,网站建设一般有哪些费用?
  企业网站建设一般有哪些费用
  
  一、域名和服务器空间费用
  网站建设时需要先申请域名,域名是什么?干什么用的?其实,域名就相当于你的企业名称,而注册域名最常见的用途就是建网站,因为它可以直接进行网站访问。一个好域名可以使你的网站在推广过程中更加省力,让目标群容易记住。网站的域名是英语顶级域名的首选。com或。cn。一般来说,使用一个域名的成本是每年几十元左右。可以说,这是整个网站建设项目成本最少的一项,几乎可以忽略不计。
  服务器是建站的基础,企业网站建设,因为图片比较少,音视频文件也不多,一般像阿里云企业版的主机都是完全够用的,其次是流量和并发数,如果网站有更多的音视频文件,流量也不低,那就是流量消耗比较大,那么选择无限流量空间,无限流量空间一般是无限并发数。企业站的服务器价格一般一年几百到两千元左右就够用了,如果后期访问流量大了,可以适当增加配置。
  二、网站页面设计价格
  一般网站页面设计价格与你所需要的网站设计的效果和功能有关,一般定制站就需要方案、美工、程序员来完成。投入费用也比较多大概在1万左右。适合大型公司及想长期运营网络营销的公司。如果想要缩小成本,就选仿站。通过修改网站的细节,完成自己的网站设计。如果对页面设计要求不高,也可以模版套用。这属于快餐式的网站设计,模版网站也是可以进行二次开发的。通过对模版的源代码进行修改。模版网站的价格一般在1千左右。
  三、后台程序开发费用
  对于企业网站要求不高的可以使用开源CMS后台管理系统,成本相对比较低,对于一般网站来说,只要没有太多的个性化定制功能需求,开源CMS完全能够满足要求。定制开发的后台功能是根据项目的功能要求来确定的,相对来说成本会高一些,响应式网站建设的功能开发成本与传统网站相差不大,这将增加一些后台定制开发成本。
  四 、后期维护费用
  网站建成后,后期保护是必要的。根据客户和企业的不同需求,分为基础维护和全包维护,因为目前网站后台的内容管理系统程序比较完善。在大多数情况下,企业只需要选择基本满足要求的标准保护,而定全包维护的费用没有标准化,要求是根据工作量确定的。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询 查看全部

  企业网站的费用和流程一览
  先说常规网站制作需要用到的东西:
  网站建设收费分三个部分 : 域名、服务器、源码(网站的设计制作)
  域名 :
  65元左右一个.com域名
  服务器 :
  企业展示型网站图片视频少,一般200元到300元左右的虚拟主机即可,如果需要承载大量宣传视频和高清案例图片,价格会贵一些。
  功能型网站,根据承载的业务量来选择服务器,价格从一千多到几千块上万不等。
  源码(网站的设计制作):
  企业/个人展示型网站一般300到500块钱。
  品牌型网站和营销型网站根据设计需要一般1000元起。
  功能型网站根据功能按需定制,价格一般一万起,开发周期正常都是最少三周起。(包含数据测试、压力测试、兼容性测试等等)。
  我们有多年稳定运行的建站软件平台,并且常年维护更新。快速帮助企业或个人完成网站搭建和上线。我们提供数千款精美网站素材和模板,且都是正版可商用,并提供云服务器和域名一键配置。快速帮助您建设制作高端大气商务网站和官方网站。
  
  您的担心:
  网站会不会被百度收录?
  内置一键提交百度收录,快速被百度收录。
  网站优化是不是很难做?
  内置配套SEO功能,只需要按提示设置关键词即可轻松优化整站和单页面搜索排名。即使不懂SEO也能轻松优化网站排名。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询
  随着互联网的发展,很多企业想要建立一个自己的企业网站,但是又苦于不懂技术,不清楚网站建设都有哪些费用和流程。下面跟大家科普一下,网站建设一般有哪些费用?
  企业网站建设一般有哪些费用
  
  一、域名和服务器空间费用
  网站建设时需要先申请域名,域名是什么?干什么用的?其实,域名就相当于你的企业名称,而注册域名最常见的用途就是建网站,因为它可以直接进行网站访问。一个好域名可以使你的网站在推广过程中更加省力,让目标群容易记住。网站的域名是英语顶级域名的首选。com或。cn。一般来说,使用一个域名的成本是每年几十元左右。可以说,这是整个网站建设项目成本最少的一项,几乎可以忽略不计。
  服务器是建站的基础,企业网站建设,因为图片比较少,音视频文件也不多,一般像阿里云企业版的主机都是完全够用的,其次是流量和并发数,如果网站有更多的音视频文件,流量也不低,那就是流量消耗比较大,那么选择无限流量空间,无限流量空间一般是无限并发数。企业站的服务器价格一般一年几百到两千元左右就够用了,如果后期访问流量大了,可以适当增加配置。
  二、网站页面设计价格
  一般网站页面设计价格与你所需要的网站设计的效果和功能有关,一般定制站就需要方案、美工、程序员来完成。投入费用也比较多大概在1万左右。适合大型公司及想长期运营网络营销的公司。如果想要缩小成本,就选仿站。通过修改网站的细节,完成自己的网站设计。如果对页面设计要求不高,也可以模版套用。这属于快餐式的网站设计,模版网站也是可以进行二次开发的。通过对模版的源代码进行修改。模版网站的价格一般在1千左右。
  三、后台程序开发费用
  对于企业网站要求不高的可以使用开源CMS后台管理系统,成本相对比较低,对于一般网站来说,只要没有太多的个性化定制功能需求,开源CMS完全能够满足要求。定制开发的后台功能是根据项目的功能要求来确定的,相对来说成本会高一些,响应式网站建设的功能开发成本与传统网站相差不大,这将增加一些后台定制开发成本。
  四 、后期维护费用
  网站建成后,后期保护是必要的。根据客户和企业的不同需求,分为基础维护和全包维护,因为目前网站后台的内容管理系统程序比较完善。在大多数情况下,企业只需要选择基本满足要求的标准保护,而定全包维护的费用没有标准化,要求是根据工作量确定的。
  网站建设、网站制作、网站设计、网站seo
  面向全国接单
  点击二维码长按识别加我为好友
  建站相关问题免费咨询

渗透技巧 | 网站后台常见的Getshell技术整理

网站优化优采云 发表了文章 • 0 个评论 • 99 次浏览 • 2022-07-20 23:46 • 来自相关话题

  渗透技巧 | 网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  
  2.网站配置
  复现:
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
  @学习更多渗透技能!体验靶场实战练习
  <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;letter-spacing: 0.544px;">(hack视频资料及工具)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /></p>
  (部分展示)
  往期推荐
  看到这里了,点个“赞”、“再看” 查看全部

  渗透技巧 | 网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  
  2.网站配置
  复现:
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
  @学习更多渗透技能!体验靶场实战练习
  <p style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;clear: both;min-height: 1em;letter-spacing: 0.544px;">(hack视频资料及工具)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /></p>
  (部分展示)
  往期推荐
  看到这里了,点个“赞”、“再看”

文库|网站后台常见的Getshell技术整理

网站优化优采云 发表了文章 • 0 个评论 • 74 次浏览 • 2022-07-16 08:32 • 来自相关话题

  文库|网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  2.网站配置
  复现:
  
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.
  回顾往期内容
  扫码白嫖视频+工具+进群+靶场等资料
  扫码白嫖!
  还有免费的配套靶场、交流群哦 查看全部

  文库|网站后台常见的Getshell技术整理
  get也叫做拿webshell,通过注入或者其他途径,获取网站管理员账号和密码后,找到后台登录地址,登录后,寻找后台漏洞上传网页后门,获取网站的webshell。
  webshell的作用是方便攻击者,webshell是拥有fso权限,根据fso权限的不用,可以对网页进行编辑,删除,上传或者下载,查看文件。渗透人员也可以通过这个webshell对服务器进行提权,提权成功后,会得到服务器管理权限。
  一.WordPress的Getshell
  WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。
  也可以把 WordPress当作一个内容管理系统(CMS)来使用。
  1.更改模板处
  复现:
  第一步:找到外观->编辑->编辑模板。
  第二步:验证
  2.上传主题
  复现:
  第一步:在上传主题处,上传一个主题压缩包,主题中需要含有木马代码。
  ps:上传成功后,压缩包会自动解压。
  上传了一个qiesi的压缩包,成功后木马被自动解压出来
  第二步:验证
  二.DedeCMS的Getshell1.任意文件上传
  dede是织梦内容管理系统dedecms的简称,是一个PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统。
  复现:
  第一步:在文件上传处,直接上传木马即可
  第二步:验证
  
  2.模板配置
  复现:
  第一步:在模板—>默认模板管理—>修改index.htm模版内容
  第二步:在生成—>更新主页的HTML中,将htm改成php后更新。
  第三步:验证
  3.广告内容
  复现:
  第一步:在 模板—>广告管理—>新增广告处
  第二步:验证
  三.南方数据CMS
  南方数据企业网站管理系统V18官方主站、企业网站SQL版、好的企业网站管理系统、企业建站系统、南方数据企业CMS、企业网站SEO、网站优化、SEO搜索引擎优化机制、自助建站系统、前台全站采用静态html页面模板自动生成。
  是由国内知名的CMS及电子商务管理软件开发商科创网络工作室**自主研发的新一代企业电子商务系统产品、同时提供各种网页模板、企业网站模板、免费企业网站系统、自动建站系统、全能型企业网站系统。
  1.00截断
  复现:
  第一步:在 新闻咨询 -> 添加新闻 -> 上传处
  第二步:上传,使用00截断
  第三步:验证
  2.网站配置
  复现:
  
  第一步:在系统管理->常量设置处,插入代码
  第二步:验证
  四.pageadmin CMS
  PageAdmin CMS系统是基于.Net的网站管理系统,安全、稳定、灵活,全国用户超过百万,致力于为企业、学校、政府网站建设和网站制作提供企业级内容管理系统解决方案。
  1.自解压 getshell
  复现:
  第一步:在文件管理处,选择模板上传,然后上传一个压缩包,其中压缩包里面包含木马。
  第二步:验证:成功。
  2.利用配置文件,连接数据库,进行getshell
  复现:
  第一步:查看配置文件
  第二步:连接数据库
  第三步:验证,可以利用数据库进行命令执行。
  申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.
  回顾往期内容
  扫码白嫖视频+工具+进群+靶场等资料
  扫码白嫖!
  还有免费的配套靶场、交流群哦

【网站搭建】-网站建设终极版本:13个教学+费用

网站优化优采云 发表了文章 • 0 个评论 • 80 次浏览 • 2022-06-26 18:48 • 来自相关话题

  【网站搭建】-网站建设终极版本:13个教学+费用
  也可以安装免费的Let's Encrypt()证书,还有其它免费安全证书可供选择,差别不大。
  主机
  05
  创建网站,除了需要一个网域,你还需要主机(又称Web hosting、网站空间、服务器)来存放网站上面内容和资料。
  Web hosting有很多种,例如独立服务器,云服务器(云主机),共享型VPS,虚拟主机,关于这几者的比较,可以参考以下我之前的总结:
  从价格来说:
  独立服务器>云服务器>VPS>虚拟主机
  从用户的维护成本来说:
  虚拟主机 从对用户的技术要求来说:
  虚拟主机
  ● 解析域名与绑定域名●
  什么是域名解析
  06
  所有的主机都是有IP地址(比如:110.110.110.110)的,但是这些IP地址太难记了,所以就出现了域名,域名解析就是将域名转换为IP地址的这样一种行为。
  DNS是什么
  07
  DNS(即域名系统,Domain Name System)控制域名的网站和电子邮件设置。当访问者转到你的域名时,其 DNS 设置将域名指向具体的网站服务器,让访客通过这个域名可以访问服务器上的网站。
  以具体例子来说人话:
  IP地址是标准门牌号,域名是昵称俗称。
  比如浦发大厦这个通俗易懂的名字就是域名。
  上海市浦东南路588号这个容易忘记的真实地址就是IP。
  DNS设置就是帮助你通过昵称俗称找到网站真实IP地址的服务。
  它如同网路世界的地址簿,把域名转换成IP -我们只须在浏览器输入域名,就能造访喜欢的网站。DNS是浏览器的指路人。
  设定DNS指向—域名解析
  08
  除了申请路标(域名),你还需要租个房子或者床位(主机/服务器)来装修成卧床(网站)。
  但你得先确认,这个路标(域名)是需要指向你租来的那个房子(主机),这就是DNS指向设定,其实也叫域名解析。
  注:很少人买得起一栋楼(独立服务器)或一层楼(云主机)。绝大多数人或企业,都是租用一个单间(共享性VPS)或者床位(虚拟主机)。
  我们来看实际操作(以Namecheap为例)...
  第一, 登入Namecheap帐户> Domain List > MANAGE >Domain:
  第二, 在NAMESERVERS栏位:
  选择Custom DNS
  贴入主机商提供的DNS位址(这个在购买的主机服务器了会提供)
  储存
  不同服务商的后台会有差异,但操作流程是一样的。
  如果不知道该怎么样用DNS指向设定,还可以用另外一种方法将域名指向主机。
  第一, 登入Namecheap帐户> Domain List > MANAGE >Advanced DNS:
  第二, 在HOST RECORDS栏位,按照如下进行设定:
  绑定域名
  09
  域名绑定实际上就是主机空间上设置权限可以让你的网站域名访问进入的设置。
  下面是流程:
  1 、登录空间商后台,进入主机管理
  2、找到你购买的主机类型,选择管理
  3、进入管理界面后,选择绑定域名
  4、在输入新域名的方框里面输入你的域名,点击增加即可
  具体过程之前在里讲的很详细,具体不再叙述。
  ●如何建设网站●
  网站建设流程有四:
  1.注册域名(申请一个路标)
  2.设定DNS指向(把路标指向你租来的那间房子)
  3.租用虚拟主机(租一间房子)
  4.安装建站程序(来装饰房子)
  根据前面的教学,你已学会第一项、第二项。
  以下,我将教你第三、四项。
  准备好了吗?开始吧!
  虚拟主机推荐
  10
  如何比较主机商?除了价格、规模、评价与24小时客服之外,你还要考虑它的机房位置。
  若你的目标访客都在大陆,虚拟主机机房最好在大陆,或邻近的亚洲国家或地区- 如新加坡、日本、香港、台湾。
  机房在地球的另一端会产生网路延迟,进而影响使用者经验。若网站是你赖以为生的工具,你当然要提供最好的“用户体验”,不是吗?
  商务网站主机我推荐SiteGround
  优点:
  价格公道(每月最低$3.95美元)
  免费SSL证书
  CDN免费加速服务
  全年无休、24小时客服
  
  Siteground真码实价
  免费的网站备份
  免费的网站迁移服务
  30天退款保证
  缺点:
  人工客服很鸡贼,常常找不到人工客服的通道。
  关于SiteGround的教学下次出一篇文章专门介绍,如果想购买的话,可以通过以下通道直达:
  博客网站主机我推荐GoDaddy 1美元主机
  关于这个1美元主机,我之前写过(点击以上链接看我以前的这篇文章),可以通过此链接直达1美元主机购买通道,否则在GoDaddy主页上购买的这个机型就不止这个价格了。
  免费主机我推荐谷歌云主机
  谷歌云主机是性能相当好的主机,而且由于在你申请谷歌云主机时,都会给你300美金试用金,相当于你使用这个主机就是免费的。
  如何申请到谷歌云的这300美金,我之前写过,最近经小伙伴反馈,这些方法部分失效,总结如下:
  P卡还能否作为申请的付款账号?
  这真得看命,亲测部分人可以,部分人被拒绝了。
  XX单标信用卡还能否申请?
  说实话,能否申请,我只能告诉你以前单标卡都是可以申请,但最近被和谐了,具体哪些单标卡没有被和谐,我也不清楚。自己手中的单标卡能否申请,try it即可,我不负责帮你回答哪些银行卡可用。
  XX信用卡为什么不能申请?
  我之前回答过,当雪崩时,没有一片雪花是无辜的,这300美金被太多人薅了,Google只好出动终极手段,双币信用卡早就被排除在可用范围之内,近期单标信用卡(就是只能使用外币的信用卡)也被踢出了局。
  还有没有申请这300美金的办法?
  有,找一个有外国信用卡的朋友帮你忙,过一段时间我再推出新的办法。
  网页建设的程序
  11
  自制网站的方式有三种:
  1. 用HTML、CSS、JavaScript... 语言,自己开发网页
  2. 使用自助建站平台,如SHOPLINE、SHOPIFY、WIX
  3. 使用CMS(Content Management System,内容管理系统)建站系统,如WordPress、Joomla!、Drupal
  若你非程序员,我建议你不要考虑第一项。
  “建站平台”是最轻松、快速之架站方式,这边,我们先讨论CMS...,关于自助建站平台Shopify与CMS WordPress以及其它的比较,我写过相关方面的。
  全球有约一半的网站,使用CMS,而全球有超过30%的网站,使用WordPress。也就是说,WordPress在CMS的市占率,超过60%。
  ● 关于WordPress程序●
  WordPress是什么
  12
  WordPress是一个内容管理系统。它有设计完善的后台,让你管理网站上所有内容,例如文章、页面、多媒体。
  WordPress的主要目的,一开始是用着建设一个博客网站,发表文章和多媒体。若你需要其他功能,如CRM、开发票...则你应该使用专门程序,而不是WordPress。
  你可以安装WordPress插件来扩充功能,WordPress有上千个插件---有免费的,也有付费的。
  如果你想把网站变成一个电子商务网站,就可以安装WooCommerce插件。
  WordPress主题(又称版型)决定网站的外观。如同插件,WordPress主题有免费、也有付费的。如前述,全球有近30%的网站是WordPress。因此市场上充满各式各样的主题及插件。
  ●WordPress教学●
  如何建设网站
  13
  在前面的URL是什么,我提到所谓“网站”,其实是由文件和数据包组成。
  一般的虚拟主机建设网站,经常要用File Manager或FTP软件,来管理这些文件和数据包,而建站平台帮你免除这些烦恼,比如电商平台的建站平台Shopify,如果你没有任何技术基础,你可以利用Shopify快速搭建一个电商网站,因为有了Shopify,你不用懂什么是服务器,SSL,FTP,CPanel,这些东西都有Shopify后台技术帮你打理,你利用主题模板就可以搭建一款与模板类似网站。
  但是如果你懂一点建站技术,我就推荐你利用WordPress+WooCommerce搭建电商网站,因为它更实惠。
  关于是用Shopify还是用WooCommerce搭建网站,请参考我的这篇文章:
  在我看来,用WordPress+WooCommerce搭建电商网站也不是太难的事,按照我这篇文章流程走下来,基本上就把一个电商网站的基础框架搭建起来。
  制作WordPress网页的流程有:
  1. 登入后台
  2.设定/更改网址结构
  3.安装WordPress主题
  4.自订外观
  5.安装插件
  6.管理留言板
  7.注册Gravatar大头贴
  8.备份WordPress网站(一键打包)
  9.角色权限管理
  10.增加影音媒体
  11.发表文章 查看全部

  【网站搭建】-网站建设终极版本:13个教学+费用
  也可以安装免费的Let's Encrypt()证书,还有其它免费安全证书可供选择,差别不大。
  主机
  05
  创建网站,除了需要一个网域,你还需要主机(又称Web hosting、网站空间、服务器)来存放网站上面内容和资料。
  Web hosting有很多种,例如独立服务器,云服务器(云主机),共享型VPS,虚拟主机,关于这几者的比较,可以参考以下我之前的总结:
  从价格来说:
  独立服务器>云服务器>VPS>虚拟主机
  从用户的维护成本来说:
  虚拟主机 从对用户的技术要求来说:
  虚拟主机
  ● 解析域名与绑定域名●
  什么是域名解析
  06
  所有的主机都是有IP地址(比如:110.110.110.110)的,但是这些IP地址太难记了,所以就出现了域名,域名解析就是将域名转换为IP地址的这样一种行为。
  DNS是什么
  07
  DNS(即域名系统,Domain Name System)控制域名的网站和电子邮件设置。当访问者转到你的域名时,其 DNS 设置将域名指向具体的网站服务器,让访客通过这个域名可以访问服务器上的网站。
  以具体例子来说人话:
  IP地址是标准门牌号,域名是昵称俗称。
  比如浦发大厦这个通俗易懂的名字就是域名。
  上海市浦东南路588号这个容易忘记的真实地址就是IP。
  DNS设置就是帮助你通过昵称俗称找到网站真实IP地址的服务。
  它如同网路世界的地址簿,把域名转换成IP -我们只须在浏览器输入域名,就能造访喜欢的网站。DNS是浏览器的指路人。
  设定DNS指向—域名解析
  08
  除了申请路标(域名),你还需要租个房子或者床位(主机/服务器)来装修成卧床(网站)。
  但你得先确认,这个路标(域名)是需要指向你租来的那个房子(主机),这就是DNS指向设定,其实也叫域名解析。
  注:很少人买得起一栋楼(独立服务器)或一层楼(云主机)。绝大多数人或企业,都是租用一个单间(共享性VPS)或者床位(虚拟主机)。
  我们来看实际操作(以Namecheap为例)...
  第一, 登入Namecheap帐户> Domain List > MANAGE >Domain:
  第二, 在NAMESERVERS栏位:
  选择Custom DNS
  贴入主机商提供的DNS位址(这个在购买的主机服务器了会提供)
  储存
  不同服务商的后台会有差异,但操作流程是一样的。
  如果不知道该怎么样用DNS指向设定,还可以用另外一种方法将域名指向主机。
  第一, 登入Namecheap帐户> Domain List > MANAGE >Advanced DNS:
  第二, 在HOST RECORDS栏位,按照如下进行设定:
  绑定域名
  09
  域名绑定实际上就是主机空间上设置权限可以让你的网站域名访问进入的设置。
  下面是流程:
  1 、登录空间商后台,进入主机管理
  2、找到你购买的主机类型,选择管理
  3、进入管理界面后,选择绑定域名
  4、在输入新域名的方框里面输入你的域名,点击增加即可
  具体过程之前在里讲的很详细,具体不再叙述。
  ●如何建设网站●
  网站建设流程有四:
  1.注册域名(申请一个路标)
  2.设定DNS指向(把路标指向你租来的那间房子)
  3.租用虚拟主机(租一间房子)
  4.安装建站程序(来装饰房子)
  根据前面的教学,你已学会第一项、第二项。
  以下,我将教你第三、四项。
  准备好了吗?开始吧!
  虚拟主机推荐
  10
  如何比较主机商?除了价格、规模、评价与24小时客服之外,你还要考虑它的机房位置。
  若你的目标访客都在大陆,虚拟主机机房最好在大陆,或邻近的亚洲国家或地区- 如新加坡、日本、香港、台湾。
  机房在地球的另一端会产生网路延迟,进而影响使用者经验。若网站是你赖以为生的工具,你当然要提供最好的“用户体验”,不是吗?
  商务网站主机我推荐SiteGround
  优点:
  价格公道(每月最低$3.95美元)
  免费SSL证书
  CDN免费加速服务
  全年无休、24小时客服
  
  Siteground真码实价
  免费的网站备份
  免费的网站迁移服务
  30天退款保证
  缺点:
  人工客服很鸡贼,常常找不到人工客服的通道。
  关于SiteGround的教学下次出一篇文章专门介绍,如果想购买的话,可以通过以下通道直达:
  博客网站主机我推荐GoDaddy 1美元主机
  关于这个1美元主机,我之前写过(点击以上链接看我以前的这篇文章),可以通过此链接直达1美元主机购买通道,否则在GoDaddy主页上购买的这个机型就不止这个价格了。
  免费主机我推荐谷歌云主机
  谷歌云主机是性能相当好的主机,而且由于在你申请谷歌云主机时,都会给你300美金试用金,相当于你使用这个主机就是免费的。
  如何申请到谷歌云的这300美金,我之前写过,最近经小伙伴反馈,这些方法部分失效,总结如下:
  P卡还能否作为申请的付款账号?
  这真得看命,亲测部分人可以,部分人被拒绝了。
  XX单标信用卡还能否申请?
  说实话,能否申请,我只能告诉你以前单标卡都是可以申请,但最近被和谐了,具体哪些单标卡没有被和谐,我也不清楚。自己手中的单标卡能否申请,try it即可,我不负责帮你回答哪些银行卡可用。
  XX信用卡为什么不能申请?
  我之前回答过,当雪崩时,没有一片雪花是无辜的,这300美金被太多人薅了,Google只好出动终极手段,双币信用卡早就被排除在可用范围之内,近期单标信用卡(就是只能使用外币的信用卡)也被踢出了局。
  还有没有申请这300美金的办法?
  有,找一个有外国信用卡的朋友帮你忙,过一段时间我再推出新的办法。
  网页建设的程序
  11
  自制网站的方式有三种:
  1. 用HTML、CSS、JavaScript... 语言,自己开发网页
  2. 使用自助建站平台,如SHOPLINE、SHOPIFY、WIX
  3. 使用CMS(Content Management System,内容管理系统)建站系统,如WordPress、Joomla!、Drupal
  若你非程序员,我建议你不要考虑第一项。
  “建站平台”是最轻松、快速之架站方式,这边,我们先讨论CMS...,关于自助建站平台Shopify与CMS WordPress以及其它的比较,我写过相关方面的。
  全球有约一半的网站,使用CMS,而全球有超过30%的网站,使用WordPress。也就是说,WordPress在CMS的市占率,超过60%。
  ● 关于WordPress程序●
  WordPress是什么
  12
  WordPress是一个内容管理系统。它有设计完善的后台,让你管理网站上所有内容,例如文章、页面、多媒体。
  WordPress的主要目的,一开始是用着建设一个博客网站,发表文章和多媒体。若你需要其他功能,如CRM、开发票...则你应该使用专门程序,而不是WordPress。
  你可以安装WordPress插件来扩充功能,WordPress有上千个插件---有免费的,也有付费的。
  如果你想把网站变成一个电子商务网站,就可以安装WooCommerce插件。
  WordPress主题(又称版型)决定网站的外观。如同插件,WordPress主题有免费、也有付费的。如前述,全球有近30%的网站是WordPress。因此市场上充满各式各样的主题及插件。
  ●WordPress教学●
  如何建设网站
  13
  在前面的URL是什么,我提到所谓“网站”,其实是由文件和数据包组成。
  一般的虚拟主机建设网站,经常要用File Manager或FTP软件,来管理这些文件和数据包,而建站平台帮你免除这些烦恼,比如电商平台的建站平台Shopify,如果你没有任何技术基础,你可以利用Shopify快速搭建一个电商网站,因为有了Shopify,你不用懂什么是服务器,SSL,FTP,CPanel,这些东西都有Shopify后台技术帮你打理,你利用主题模板就可以搭建一款与模板类似网站。
  但是如果你懂一点建站技术,我就推荐你利用WordPress+WooCommerce搭建电商网站,因为它更实惠。
  关于是用Shopify还是用WooCommerce搭建网站,请参考我的这篇文章:
  在我看来,用WordPress+WooCommerce搭建电商网站也不是太难的事,按照我这篇文章流程走下来,基本上就把一个电商网站的基础框架搭建起来。
  制作WordPress网页的流程有:
  1. 登入后台
  2.设定/更改网址结构
  3.安装WordPress主题
  4.自订外观
  5.安装插件
  6.管理留言板
  7.注册Gravatar大头贴
  8.备份WordPress网站(一键打包)
  9.角色权限管理
  10.增加影音媒体
  11.发表文章

【网站模板】第01期—15套免费网站后台管理模板

网站优化优采云 发表了文章 • 0 个评论 • 76 次浏览 • 2022-06-21 13:41 • 来自相关话题

  【网站模板】第01期—15套免费网站后台管理模板
  
  作者 | web小二
  来源 | web前端开发公众号(ID:web_qdkf)
  很早之前,我跟大家分享过一期关于网站后台管理的文章《》在这篇文章中,我跟大家讲了,我之前因为在企业做可视项目的时候,找了很多案例进行参考,但是一直没有把它们全部整理处理进行分享,上次只是精选了一些我认为比较好的模板案例分享给大家。这一次,我想把这个源码模板案例作为一个长期的免费学习资料分享给大家,希望对大家学习有帮助。
  后面每期内容大概会分享10-15款网站源码模板,这些网站模板都是我通过网络收集整理而成,希望对大家有所帮助。下面就开始今天的第一期内容。
  01、订单销售统计电商后台系统
  这是一款使用Bootstrap构建的电商后台管理系统页面模板。里面包含订单销售、商品管理、销售营业额统计后台管理页面;还有多个ui组件,图表库、日历、文本表单、日期范围、上传区域,形成自动完成,滑块范围,进度条、通知消息等。下载地址: 访问密码:269802、电商业务数据统计后台模板
  这一款后台管理模板是基于vue实现的电商app,电商订单,电商销售数据统计后台管理系统模板。适合电子商务商城网站admin系统。界面使用tab选项卡的方式,无刷新效果很好。这套后台模板是github项目,请参考帮助文档。ps:如果不懂vue,也没有编程基础的话,不建议直接学习。下载地址: 访问密码:269803、H5物流大数据展示后台投票模板
  
  这一款科技感十足的物流大数据系统,物流数据概况系统,物流订单系统,物流信息系统后台多个展示大屏模板。ps:本地需在localhost下进行访问。下载地址: 访问密码:269804、App商城销售后台统计页面模板
  这一款是基于bootstrap构建,中文版的商品销售统计管理,商城订单销售,商城累计收入统计后台管理UI框架模板。包含完整的UI元素页面,是个通用的前端后台框架模板。下载地址: 访问密码:269805、课程教育系统管理后台模板
  
  这款是基于bootstrap框架和jquery插件,多用途的教育行业以及网络课程系统管理,是一套教育平台网站后台页面模板。这套管理后台模板用途很广泛,适用于教育管理软件,很容易修改定制。下载地址: 访问密码:269806、电商业务销售管理系统模板
  
  这款是基于bootstrap框架构建的蓝色多用途电商产品业务销售管理系统,里面有每月营业额统计管理UI框架模板。下载地址: 访问密码:269807、医院就诊统计管理模板
  
  这一款多用途的医院医生就诊统计,医疗服务统计管理后台HTML模板。适用于:医院、医疗行业管理系统,当然,你也可以使用这套模板创建任何类型的管理软件,或者网站后台、数据统计分析等。下载地址: 访问密码:269808、电商业务销售统计后台界面模板
  
  这款模板是基于bootstrap前端框架构建的,电商销售统计/公司业绩销售管理后台模板。适用于任何类型的电商网站后台,管理应用软件web前端模板等。下载地址: 访问密码:269809、广告流量分析统计管理后台模板
  这款也是基于Bootstrap构建的,黑色的app后台流量统计,访客数量统计,广告自媒体流量统计管理后台ui框架模板。使用了最新jQuery UI组件和Bootstrap插件。适用于任何的web应用程序电子商务仪表板,定制管理面板,crm、cms项目管理管理等。下载地址: 访问密码:269810、产品订单销售电商后台模板
  这是一款基于Bootstrap构建,产品订单管理/产品销售/电商后台系统模板。模板附带很多小部件和组件。它有一个巨大的可重用的UI组件集成模板。下载地址: 访问密码:269811、云文件存储管理后台模板
  
  这个是一款多功能的云端图片文件管理,云共享,云储存后台管理系统模板。它由用户管理模块、auth模块、ui页面、表单页面等响应式后台页面布局。下载地址: 访问密码:2698
  12、响应式app业务数据统计后台模板
  
  这款模板基于bootstrap框架,jQuery构建,响应式的app数据统计管理后台模板。包含很多UI元素、组件、web应用程序、数据仪表板、CRM、CMS、电子商务面板页面等。它有很多可以使用页面,如身份验证、电子邮件、日历、错误、faq、博客文章、搜索、用户配置文件等。
  下载地址: 访问密码:2698
  13、健身App管理后台模板
  
  这款模板基于Bootstrap构建,响应式的运动健身App统计管理,健身项目管理,私人健身服务后台管理模板。下载地址: 访问密码:269814、餐饮业务管理系统后台模板
  这款模板是基于html5与 Bootstrap构建的,可以在餐饮行业进行使用,餐饮电商系统,餐饮外卖订单,餐饮业务销售管理响应式后台模板。
  下载地址: 访问密码:269815、企业网站后台管理页面模板
  这款后面模板是基于Bootstrap构建,轻量级的BsAdmin企业网站后台模板,风格简洁简单,是中小型项目首选,不管你是初级还是高级工程师,都有可以快速上手。BsAdmin是由Bootstrap4开发,可以在模板任意使用jq或vue。下载地址: 访问密码:2698
  本文完〜
   查看全部

  【网站模板】第01期—15套免费网站后台管理模板
  
  作者 | web小二
  来源 | web前端开发公众号(ID:web_qdkf)
  很早之前,我跟大家分享过一期关于网站后台管理的文章《》在这篇文章中,我跟大家讲了,我之前因为在企业做可视项目的时候,找了很多案例进行参考,但是一直没有把它们全部整理处理进行分享,上次只是精选了一些我认为比较好的模板案例分享给大家。这一次,我想把这个源码模板案例作为一个长期的免费学习资料分享给大家,希望对大家学习有帮助。
  后面每期内容大概会分享10-15款网站源码模板,这些网站模板都是我通过网络收集整理而成,希望对大家有所帮助。下面就开始今天的第一期内容。
  01、订单销售统计电商后台系统
  这是一款使用Bootstrap构建的电商后台管理系统页面模板。里面包含订单销售、商品管理、销售营业额统计后台管理页面;还有多个ui组件,图表库、日历、文本表单、日期范围、上传区域,形成自动完成,滑块范围,进度条、通知消息等。下载地址: 访问密码:269802、电商业务数据统计后台模板
  这一款后台管理模板是基于vue实现的电商app,电商订单,电商销售数据统计后台管理系统模板。适合电子商务商城网站admin系统。界面使用tab选项卡的方式,无刷新效果很好。这套后台模板是github项目,请参考帮助文档。ps:如果不懂vue,也没有编程基础的话,不建议直接学习。下载地址: 访问密码:269803、H5物流大数据展示后台投票模板
  
  这一款科技感十足的物流大数据系统,物流数据概况系统,物流订单系统,物流信息系统后台多个展示大屏模板。ps:本地需在localhost下进行访问。下载地址: 访问密码:269804、App商城销售后台统计页面模板
  这一款是基于bootstrap构建,中文版的商品销售统计管理,商城订单销售,商城累计收入统计后台管理UI框架模板。包含完整的UI元素页面,是个通用的前端后台框架模板。下载地址: 访问密码:269805、课程教育系统管理后台模板
  
  这款是基于bootstrap框架和jquery插件,多用途的教育行业以及网络课程系统管理,是一套教育平台网站后台页面模板。这套管理后台模板用途很广泛,适用于教育管理软件,很容易修改定制。下载地址: 访问密码:269806、电商业务销售管理系统模板
  
  这款是基于bootstrap框架构建的蓝色多用途电商产品业务销售管理系统,里面有每月营业额统计管理UI框架模板。下载地址: 访问密码:269807、医院就诊统计管理模板
  
  这一款多用途的医院医生就诊统计,医疗服务统计管理后台HTML模板。适用于:医院、医疗行业管理系统,当然,你也可以使用这套模板创建任何类型的管理软件,或者网站后台、数据统计分析等。下载地址: 访问密码:269808、电商业务销售统计后台界面模板
  
  这款模板是基于bootstrap前端框架构建的,电商销售统计/公司业绩销售管理后台模板。适用于任何类型的电商网站后台,管理应用软件web前端模板等。下载地址: 访问密码:269809、广告流量分析统计管理后台模板
  这款也是基于Bootstrap构建的,黑色的app后台流量统计,访客数量统计,广告自媒体流量统计管理后台ui框架模板。使用了最新jQuery UI组件和Bootstrap插件。适用于任何的web应用程序电子商务仪表板,定制管理面板,crm、cms项目管理管理等。下载地址: 访问密码:269810、产品订单销售电商后台模板
  这是一款基于Bootstrap构建,产品订单管理/产品销售/电商后台系统模板。模板附带很多小部件和组件。它有一个巨大的可重用的UI组件集成模板。下载地址: 访问密码:269811、云文件存储管理后台模板
  
  这个是一款多功能的云端图片文件管理,云共享,云储存后台管理系统模板。它由用户管理模块、auth模块、ui页面、表单页面等响应式后台页面布局。下载地址: 访问密码:2698
  12、响应式app业务数据统计后台模板
  
  这款模板基于bootstrap框架,jQuery构建,响应式的app数据统计管理后台模板。包含很多UI元素、组件、web应用程序、数据仪表板、CRM、CMS、电子商务面板页面等。它有很多可以使用页面,如身份验证、电子邮件、日历、错误、faq、博客文章、搜索、用户配置文件等。
  下载地址: 访问密码:2698
  13、健身App管理后台模板
  
  这款模板基于Bootstrap构建,响应式的运动健身App统计管理,健身项目管理,私人健身服务后台管理模板。下载地址: 访问密码:269814、餐饮业务管理系统后台模板
  这款模板是基于html5与 Bootstrap构建的,可以在餐饮行业进行使用,餐饮电商系统,餐饮外卖订单,餐饮业务销售管理响应式后台模板。
  下载地址: 访问密码:269815、企业网站后台管理页面模板
  这款后面模板是基于Bootstrap构建,轻量级的BsAdmin企业网站后台模板,风格简洁简单,是中小型项目首选,不管你是初级还是高级工程师,都有可以快速上手。BsAdmin是由Bootstrap4开发,可以在模板任意使用jq或vue。下载地址: 访问密码:2698
  本文完〜
  

用这些后台管理模版后,三天完成项目!

网站优化优采云 发表了文章 • 0 个评论 • 92 次浏览 • 2022-06-20 14:40 • 来自相关话题

  用这些后台管理模版后,三天完成项目!
  前言
  你是否遇到过PM今天丢给你一堆后台管理系统的需求文档,并说这个产品下个星期上线没有问题吧!
  
  然后你是不是就已经做好了007奋战项目的准备了,其实大可不必,我们首先需要做的是技术选型,然后基于这个框架去完成需求,因为框架的加持可以给我们带来很多的开发便利,提高写代码的效率。
  这里找了几款Vue的后台管理模版,希望给同样被PM安排写需求的你代码写起来能够"策马奔腾"。
  Vue Element Admin
  github获得⭐ 70.2k
  github地址:
  vue-element-admin 是一个后台管理系统案例,它基于 vue 和 element-ui实现,使用最新的前端技术栈,内置了 i18n 国际化解决方案。动态路由、权限验证、提炼了典型的业务模型,提供了丰富的*功能组件,可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
  
  vue2-manage
  github获得⭐ 11.0k
  github地址:
  vue2-manage 是一个前端后端系统、手机端系统的案例,它是基于 vue2 + vuex + vue-router + webpack + ES6/7 + less + element-ui 完成的,后端则采用 nodejs + express + mongodb + mongoose 的架构,客户端采用基于 Flutter 构建的兼容IOS和Android的原生APP.可以说是比较完整的一个前端、后端、用户端都包含的餐饮行业的完整项目了。有兴趣自己搭建完整项目练手的小伙伴可以参考参考。
  PC管理后台:
  APP客户端:
  
  非常适合遇到做电商项目的基础搭建架构。
  
  妈妈再也不用担心我不会做电商系统了。
  vue-manage-system
  github获得⭐ 13.5k
  github地址:
  vue-manage-system 是一个 Vue3 + Element Plus 的后台管理系统解决方案。使用 vue-cli3 脚手架,引用 Element Plus 组件库,方便开发快速简洁好看的组件。支持手动切换主题色,而且很方便使用自定义主题色,并且使用含有富文本的案例。
  
  mall-admin-web
  github获得⭐ 8.7k
  github地址:
  mall-admin-web 是一个 电商后台管理系统 的前端项目,基于 Vue+Element 实现。主要包括 商品管理、订单管理 、会员管理 、促销管理 、运营管理 、内容管理 、统计报表 、财务管理 、权限管理 、设置等功能。对于电商后台管理系统来说非常全面了。
  技术选型:
  预览界面:
  
  角色分配也相当明确:
  
  当然它也配备了手机端的项目:
  
  
  都是非常不错的案例,对应的后台代码也有发布出来。后端代码基于 SpringBoot+MyBatis 实现,采用 Docker 容器化部署。有兴趣的小伙伴自行翻阅。
  RuoYi-Vue
  gitee获得⭐ 11.3k
  gitee地址:
  若依是一个开源项目,用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手。
  它有自己的开发文档介绍和使用手册。
  
  
  jeecg-boot
  github获得⭐ 24.6k
  github地址:
  jeecg-boot 号称是一款基于 代码生成器 的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发!
  它可以应用在任何J2EE项目的开发中,尤其适合SAAS项目、企业信息管理系统(MIS)、内部办公系统(OA)、企业资源计划系统(ERP)、客户关系管理系统(CRM)等,其半智能手工Merge的开发方式,可以显著提高开发效率70%以上,极大降低开发成本。
  
  
  内容太多,就不一一截图展示了,有兴趣的小伙伴自行查阅参考吧。另外,这里的数据库设计也相当巧妙!后端的大佬可以参考下。 查看全部

  用这些后台管理模版后,三天完成项目!
  前言
  你是否遇到过PM今天丢给你一堆后台管理系统的需求文档,并说这个产品下个星期上线没有问题吧!
  
  然后你是不是就已经做好了007奋战项目的准备了,其实大可不必,我们首先需要做的是技术选型,然后基于这个框架去完成需求,因为框架的加持可以给我们带来很多的开发便利,提高写代码的效率。
  这里找了几款Vue的后台管理模版,希望给同样被PM安排写需求的你代码写起来能够"策马奔腾"。
  Vue Element Admin
  github获得⭐ 70.2k
  github地址:
  vue-element-admin 是一个后台管理系统案例,它基于 vue 和 element-ui实现,使用最新的前端技术栈,内置了 i18n 国际化解决方案。动态路由、权限验证、提炼了典型的业务模型,提供了丰富的*功能组件,可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
  
  vue2-manage
  github获得⭐ 11.0k
  github地址:
  vue2-manage 是一个前端后端系统、手机端系统的案例,它是基于 vue2 + vuex + vue-router + webpack + ES6/7 + less + element-ui 完成的,后端则采用 nodejs + express + mongodb + mongoose 的架构,客户端采用基于 Flutter 构建的兼容IOS和Android的原生APP.可以说是比较完整的一个前端、后端、用户端都包含的餐饮行业的完整项目了。有兴趣自己搭建完整项目练手的小伙伴可以参考参考。
  PC管理后台:
  APP客户端:
  
  非常适合遇到做电商项目的基础搭建架构。
  
  妈妈再也不用担心我不会做电商系统了。
  vue-manage-system
  github获得⭐ 13.5k
  github地址:
  vue-manage-system 是一个 Vue3 + Element Plus 的后台管理系统解决方案。使用 vue-cli3 脚手架,引用 Element Plus 组件库,方便开发快速简洁好看的组件。支持手动切换主题色,而且很方便使用自定义主题色,并且使用含有富文本的案例。
  
  mall-admin-web
  github获得⭐ 8.7k
  github地址:
  mall-admin-web 是一个 电商后台管理系统 的前端项目,基于 Vue+Element 实现。主要包括 商品管理、订单管理 、会员管理 、促销管理 、运营管理 、内容管理 、统计报表 、财务管理 、权限管理 、设置等功能。对于电商后台管理系统来说非常全面了。
  技术选型:
  预览界面:
  
  角色分配也相当明确:
  
  当然它也配备了手机端的项目:
  
  
  都是非常不错的案例,对应的后台代码也有发布出来。后端代码基于 SpringBoot+MyBatis 实现,采用 Docker 容器化部署。有兴趣的小伙伴自行翻阅。
  RuoYi-Vue
  gitee获得⭐ 11.3k
  gitee地址:
  若依是一个开源项目,用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手。
  它有自己的开发文档介绍和使用手册。
  
  
  jeecg-boot
  github获得⭐ 24.6k
  github地址:
  jeecg-boot 号称是一款基于 代码生成器 的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发!
  它可以应用在任何J2EE项目的开发中,尤其适合SAAS项目、企业信息管理系统(MIS)、内部办公系统(OA)、企业资源计划系统(ERP)、客户关系管理系统(CRM)等,其半智能手工Merge的开发方式,可以显著提高开发效率70%以上,极大降低开发成本。
  
  
  内容太多,就不一一截图展示了,有兴趣的小伙伴自行查阅参考吧。另外,这里的数据库设计也相当巧妙!后端的大佬可以参考下。

CmsEasy7.3.8后台任意文件读取漏洞

网站优化优采云 发表了文章 • 0 个评论 • 236 次浏览 • 2022-06-20 12:29 • 来自相关话题

  CmsEasy7.3.8后台任意文件读取漏洞
  想学习交流网络安全技术吗?文末扫码入群
  
  0x01漏洞简述
  
  CmsEasy7.3.8版本中存在后台任意文件读取漏洞,漏洞产生原因是,网站的后台模板编辑功能中atlas.html这个接口没有做好限制和过滤,导致可以读取任意传参文件,例如数据库配置文件。
  0x02知识扩展
  
  CmsEasy(中文名:易通企业CMS),是一款基于PHP+MySql架构的网站内容管理系统,由九州易通科技有限公司开发,系统前台生成html、完全符合SEO、同时有在线客服、潜在客户跟踪、便捷企业网站模板制作、搜索引擎推广等功能的企业网站系统。是国内为数不多可以免费提供模板的企业网站系统。
  Search Engine Optimization,简称SEO:汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。
  0x03风险等级
  
  漏洞的评定结果如下:
  评定方式 等级
  威胁等级严重
  影响面 广泛
  0x04影响版本
  
  CmsEasy7.3.8
  0x05漏洞环境搭建
  
  所需系统环境及配置信息
  靶机
  操作系统:windows7
  IP:172.16.16.71
  攻击机
  操作系统:windows10
  IP:172.16.16.53
  所需工具
  安装步骤
  1、点击下载PHPatudy,下载地址:
  https://public.xp.cn/upgrades/phpStudy_64.zip
  2、解压后双击安装,启动Apache服务和mysql服务。
  
  3、点击下载CmsEasy7.3.8,下载地址:
  https://ftp.cmseasy.cn/CmsEasy ... 0.zip
  4、创建网站,将下载好的Cmseasy解压到phpstudy网站根目录下(安装盘符\phpstudy_pro\WWW),点击网站---->创建网站---->域名为靶机IP 172.16.16.71
  注意:phpstudy的根目录也要设置。根目录选择网站安装的路径即可。
  
  5、选择创建好的站点,点击网站,右边【管理】按钮,在下拉菜单中选择【打开网站】,开始安装。设置好数据库名,用户密码点击开始安装即可。
  6、安装成功(注:太低的浏览器版本无法登陆网站后台)
  
  0x06漏洞验证
  
  1、进入管理界面-->模块-->编辑模板
  
  2、观察模板编辑功能,存在对模板的html文件的读取(查看操作),对应到HTTP请求可以明显看到可控参数。
  3、打开Burp Suite,设置浏览器代理,点击查看,开始抓包。
  4、看到可控参数,手动修改ID后发现这个接口没有做好限制和过滤。CTRL+R发送至reperter(重放)模块,修改ID为
  …/…/config/config_database.php
  点击send发送,发现返回了数据库名和用户密码。
  0x07修复建议
  
  1、升级到7.3.8以上版本。
  2、接口做好限制和过滤。
  
  往期回顾:
  欢迎加入海狼技术交流群:
  海狼科技官方微博:
  如果您遇到网络安全问题
  欢迎致电:0991-8156363
  或发送至:
  新疆海狼科技,您身边的网络安全助理 查看全部

  CmsEasy7.3.8后台任意文件读取漏洞
  想学习交流网络安全技术吗?文末扫码入群
  
  0x01漏洞简述
  
  CmsEasy7.3.8版本中存在后台任意文件读取漏洞,漏洞产生原因是,网站的后台模板编辑功能中atlas.html这个接口没有做好限制和过滤,导致可以读取任意传参文件,例如数据库配置文件。
  0x02知识扩展
  
  CmsEasy(中文名:易通企业CMS),是一款基于PHP+MySql架构的网站内容管理系统,由九州易通科技有限公司开发,系统前台生成html、完全符合SEO、同时有在线客服、潜在客户跟踪、便捷企业网站模板制作、搜索引擎推广等功能的企业网站系统。是国内为数不多可以免费提供模板的企业网站系统。
  Search Engine Optimization,简称SEO:汉译为搜索引擎优化。是一种方式:利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。很大程度上是网站经营者的一种商业行为,将自己或自己公司的排名前移。
  0x03风险等级
  
  漏洞的评定结果如下:
  评定方式 等级
  威胁等级严重
  影响面 广泛
  0x04影响版本
  
  CmsEasy7.3.8
  0x05漏洞环境搭建
  
  所需系统环境及配置信息
  靶机
  操作系统:windows7
  IP:172.16.16.71
  攻击机
  操作系统:windows10
  IP:172.16.16.53
  所需工具
  安装步骤
  1、点击下载PHPatudy,下载地址:
  https://public.xp.cn/upgrades/phpStudy_64.zip
  2、解压后双击安装,启动Apache服务和mysql服务。
  
  3、点击下载CmsEasy7.3.8,下载地址:
  https://ftp.cmseasy.cn/CmsEasy ... 0.zip
  4、创建网站,将下载好的Cmseasy解压到phpstudy网站根目录下(安装盘符\phpstudy_pro\WWW),点击网站---->创建网站---->域名为靶机IP 172.16.16.71
  注意:phpstudy的根目录也要设置。根目录选择网站安装的路径即可。
  
  5、选择创建好的站点,点击网站,右边【管理】按钮,在下拉菜单中选择【打开网站】,开始安装。设置好数据库名,用户密码点击开始安装即可。
  6、安装成功(注:太低的浏览器版本无法登陆网站后台)
  
  0x06漏洞验证
  
  1、进入管理界面-->模块-->编辑模板
  
  2、观察模板编辑功能,存在对模板的html文件的读取(查看操作),对应到HTTP请求可以明显看到可控参数。
  3、打开Burp Suite,设置浏览器代理,点击查看,开始抓包。
  4、看到可控参数,手动修改ID后发现这个接口没有做好限制和过滤。CTRL+R发送至reperter(重放)模块,修改ID为
  …/…/config/config_database.php
  点击send发送,发现返回了数据库名和用户密码。
  0x07修复建议
  
  1、升级到7.3.8以上版本。
  2、接口做好限制和过滤。
  
  往期回顾:
  欢迎加入海狼技术交流群:
  海狼科技官方微博:
  如果您遇到网络安全问题
  欢迎致电:0991-8156363
  或发送至:
  新疆海狼科技,您身边的网络安全助理

跨境电商从0到100:企业该如何选择建站系统

网站优化优采云 发表了文章 • 0 个评论 • 92 次浏览 • 2022-06-20 12:09 • 来自相关话题

  跨境电商从0到100:企业该如何选择建站系统
  
  写在前面的话:
  最近跨境圈可谓风起云涌,亚马逊众多头部玩家纷纷暴雷:全部店铺账号被封,几亿甚至是几十亿的资产被套牢,员工晚上打卡,第二天收到企业遣散通知……亚马逊卖家人人自危。
  
  这个时候,大家也都意识到了,拥有自主话语权的网站和品牌是多么的重要。因此独立站成为新的跨境风口。但风口里面也会有砂砾甚至是石头,你碰到了不会死但是可能会受伤或者让你难受一下。在独立站建设过程中,部分人也会遇到一些大坑或者是不靠谱的人,所以我们推出了从独立站到品牌营销系列。帮助大家在认知上了解独立站从建站到优化过程中所涉及的问题以及解决方案,希望可以帮助大家少踩一些坑。大家可以通过链接观看之前的几篇文章:今天要给大家分享的是企业该如何选择建站系统。
  Part 1、常见的建站系统
  市面上常见的建站系统,有两种:传统建站和CMS建站系统
  传统建站
  传统建站,顾名思义,最传统的利用代码建站的方式。利用代码建站是所有建站系统的基础。
  
  但是对于没有代码基础的人来说,这种建站方式难度太高,且后期的修改、操作只能是依靠专业的技术人员,可操控性不强。因此也就衍生出了CMS建站系统。
  CMS建站系统
  CMS,是content management system的缩写,即内容管理系统,是一种用来创建内容的网页模板。简单点来说,就是技术人员利用代码写出来一套程序,你只需要将内容上传上去,系统可自动的生成相关的网页。
  它允许多位成员同时进行创建、编辑、发布。用户上传的内容会存储在数据库中,并基于网站模板进行显示。
  
  对比传统的建站方式,CMS建站系统具有以下的优势:
  大家耳熟能详的Wordpress和Shopify都属于CMS建站系统。
  那么,接下来我们来看一下国内、国外常见的CMS建站系统有哪些,以及各自的优势所在:
  国内常见的CMS建站系统
  在我国,经常使用到的建站系统有PageAdmin、织梦DEDECMS、帝国系统, PHPCMS系统等不同的CMS系统,那么我们来看一下这些系统都有哪些区别以及优劣势。
  PageAdmin CMS建站系统(⭐️⭐️⭐️⭐️⭐️)
  PageAdmin CMS建站系统()是国内应用最受欢迎的建站系统之一,大部分的外贸网站都是PageAdmin建成的。它的模板丰富、功能强大、可拓展性强,可以轻松的帮你打造一个独具特色的网站,那么我们来盘点一下,该系统的优缺点:
  优点:
  缺点:
  织梦 DEDE CMS(⭐️⭐️)
  织梦也是国内知名的老牌建站系统了,主要是面向中小企业以及个人站长的新闻内容管理平台。但是其原始创作团队解散之后,这一系统已经不再进行更新和维护了,因此我们看到的织梦DEDE CMS的操作后台比较老化。
  
  织梦DEDE CMS的模板较为简单,可拓展性很差,适合没有定制需求的新手来进行操作。其最令人诟病的地方就是网站的安全性方面,因为织梦是开源的,所以DEDE做的站经常被黑,这个已经是众所周知的事情。
  优点:
  缺点:
  帝国CMS(⭐️⭐️⭐️)
  
  帝国CMS建站系统()是2002年推出的一款CMS建站系统,系统采用老式的表格布局模式,后台非常的复杂,因此对于新手来说不友好。但是其模板标签拓展灵活,但是需要用户有一定的代码基础。
  优点:
  缺点:
  PHPCMS(⭐️⭐️)
  
  PHPCMS适合用来进行二次开发,它的系统底层架构做得不错,承载也很强大,但是需要开发者掌握Html ,PHP, Mysql等技术语言。技术采用模块化方式开发,功能易用便于扩展,采用mvc模式,技术相对其他cms来说,算新的。可惜的是phpcms在2020年初已经关站倒闭。建议大家谨慎选择。
  优点:
  缺点:
  以上的这些就是企业站经常使用到的国内的建站系统。除了这些系统以外,还有一些专门建站博客或者是新闻网站的建站程序,这里大家可以参考一下:
  国外常见的CMS建站系统
  说到国外的CMS建站系统,Wordpress, Shopify, Magento, Bigcommerce等系统都是大家耳熟能详的建站系统,除此以外,还有其他一些在国外比较常用,但是国内很少用到的系统,比如Joomla,Durpal, Sharepoint等。在这里我们来看一下这些网站的优劣势:
  Wordpress建站系统(⭐️⭐️⭐️⭐️⭐️)
  
  Wordpress系统是全球使用最广泛的开源CMS建站系统, 互联网上35%的网站是由WordPress系统建设而成。该平台是在2003年推出,此后凭借简单易上手的操作后台,丰富的模板和插件、良好的拓展性,使其在众多的CMS建站系统中脱颖而出。
  优点:
  缺点:
  Shopify建站系统(⭐️⭐️⭐️⭐️)
  Shopify是一个托管电子商务平台,专门用来建设在线零售商店。这一系统非常适合新手网上开店,无需购买任何主机、管理备份和安全,只需要支付29-299美金,你就可以使用Shopify系统了。
  
  除了最基础的版本, Shopify还推出了每月2000美金的Shopify Plus计划, 与之相对应的是更全面的功能:专属的客户经理、更多的主题和App选择、产品页面支持AR, Video, 3D视频、同一面板同时管理多个Shopify店铺, 更加细致的数据分析功能以及优化完善后的支付系统等。
  优点:
  缺点:
  Magento(⭐️⭐️⭐️⭐️)
  
  Magento是 Adobe 旗下的电子商务平台,可以为精通代码技术的店主提供无限可能。Magento提供两个版本的建站系统: Magento Open Source 和 Magento Commerce.
  使用Magento Open Source,你可以下载一个免费的开源建站系统
  那么 Magento Commerce就是专门针对商业方面的建站了,收费比较昂贵。
  优点:
  缺点:
  Bigcommerce(⭐️⭐️⭐️⭐️)
  Bigcommerce是一个一体化的在线电子商务平台,它的性质和Shopify差不多。如果你对代码一窍不通,那么这个平台的话,很适合你。
  
  Bigcommerce平台是收费的,但是你可以免费试用。因为平台是一站式的管理系统,所以不需要额外的购买服务器、域名(域名平台可以免费提供,类似于,当然你也可以自行购买)。
  平台提供丰富的模板和插件,可以实现高度的自定义设计。因为主要为电子商务设计,所以可以在不影响速度的前提下,上传大量的产品、图片和文章。后台操作界面非常的清晰,简单,适合新手操作。
  优点:
  缺点:
  Joomla(⭐️⭐️⭐️)
  
  Joomla也是一个免费的开源CMS建站系统。平台成立于2005年。它和Wordpress一样,已经发展了很多年,而且平台中模板和插件非常的丰富,可拓展性非常的强。对比其他的建站系统,Joomla拥有更强大的内置功能。依靠其内置功能,用户可以轻松的使用多语言创建页面,以及创建不同模板和类型的文章页面等。但是在国内的话,很少有企业使用这一系统,因此相关的技术人员也很难找到。
  优点:
  缺点:
  Drupal(⭐️⭐️⭐️)
  Drupal也是一个开源的CMS系统,可以用来创建大型网站、个人博客和新闻网站等。由于该平台是专门为研发人员进行设计的,所以使用者必须要对 PHP、HTML 和 CSS 有一定的了解才能充分的利用Drupal的全部功能。
  
  Drupal CMS建站功能拥有数千个模板和插件可供选择,可实现高度的自定义设计功能。多语言功能内置到系统中,可以轻松实现多语言切换。另外,其安全性也是所有的CMS建站系统中首屈一指的。
  优点:
  缺点:
  Part2、外贸企业挑选建站系统注意事项
  上面我们盘点了那么多的建站系统,那么我们该选择哪一个呢?在选择之前,建议大家从以下的角度来进行考量
  1、系统的易用性
  优秀的CMS系统,可以让你非常简单轻松的就能上传、编辑管理你的内容。这种系统的后台一般都支持拖放功能,可以让你在页面中添加不同的模块和元素。
  2、系统功能完善、成熟度高、用户量大
  只有系统功能完善的CMS系统才能实现你对网站的所有设想。如果系统不完善,不成熟的话,会导致功能无法实现,影响网站的建设。系统功能完善,成熟度高、用户量大、这样的系统才有较高的实用性,满足企业的基础功能需求,利于后期自行维护
  3、安全性(非常重要!!!)
  CMS系统的安全性是我们需要重点衡量的一个因素,毕竟好不容易建了一个网站,谁都不希望这个网站受到黑客的攻击。所以CMS系统是不是经常进行更新,安装补丁,以及是否有相关的工作人员/社区进行技术上的支持就非常的重要了。除了系统的安全性,我们还要考虑到数据信息的安全性。其中包括流量信息、订单信息、客户信息等。如果这些数据可以被第三方轻易的获取,那么网站的损失就大了。
  4、系统是否是开源系统
  国外的大多数CMS建站系统都是开源系统。开源系统意味着代码向公众进行开放,易用性就会比较高。你可以轻松的在建站公司那边获得网站源代码(国内很多公司自己的系统,是不会提供共源代码给你的,也就意味着你只是租了一个房间,最终的所有的东西都还是建站公司的。)
  5、模板和插件的丰富度
  模板和插件比较多的话,可以提供更高的自由度来修改我们的网站。可拓展性比较强
  6、搜索引擎优化
  CMS系统是否针对搜索引擎进行过优化,以及是否有第三方的插件支持网站进行搜索引擎优化。毕竟网站建了之后就是要在搜索引擎上面做排名的。如果CMS系统对搜索引擎不友好的话,网站建设了意义也不大。
  7、售后以及技术支持
  网站就像一台庞大的机器,当这个机器出问题了,你需要看一下,是不是有足够的技术支持可以帮助你解决这一问题。找不到技术支持,或者解决问题速度太慢,都会影响网站的正常工作。
  结合以上的7种元素,在这里推荐大家使用以下的建站系统进行建站:
  那么接下来,我们以WordPress为例,教给大家如何7步建成独立站。
  Part3、7步建成独立站
  01
  挑选域名
  在建站之前,你要先确定你的网站名称,并购买域名。选择一个合适的域名没有那么简单的。关于如何挑选域名,可参考我们之前的文章-《
  02
  挑选服务器
  关于如何挑选服务器,可参考我们之前的文章-《
  03
  安装Wordpress
  不管你的服务器,挑选的是Siteground, Bluehost, 还是Inmotion Hosting, 这些大的网站后台都集成了WordPress安装,只需要简单的操作即可进行安装,在这里,以Inmotion Hosting为例,
  1、登陆Inmotion Hosting控制面板-cPanel
  2、找到Software板块,点击 Softaculous Apps installer
  
  3、点开后选择Wordpress的标志,点开就能看到安装的界面,点击“install”进行安装
  4、按照要求填写WordPress安装信息
  5、Softaculous Apps installer会检查你填写和提交的数据,并将wordpress文件安装到你的服务器上面。点击返回概览,你会在当前安装列表中看到你的WordPress安装进度。
  
  04
  挑选模板并进行自定义
  网站除了要有优秀的文字内容来吸引用户外,还需要有漂亮的网页设计。Wordpress系统中提供了大量的免费和付费的网站模板可供用户来进行选择,我们只需要点开Wordpress后台Apperance-Themes就可以看到系统提供的免费模板。
  
  点击“Add New" 进入模板库,在模板库里面选择自己心仪的网站模板进行安装并激活就可以应用到网站上面。
  
  除了在worpress模板库里面直接安装模板,我们还可以到第三方网站上面去购买WordPress的模板。很多第三方网站上面的WordPress模板是专业的技术人员进行开发或者是优化过后的,展示效果和优化效果都很好。
  著名的WordPress模板出售网站有以下几个:
  在这些网站上面购买的模板有另外一种方法进行安装:登陆Wordpress后台-点击Apperance-Add New
  进去之后,点击 Upload Theme,将你从第三方网站上购买到的WordPress模板文件.zip上传,激活并安装。
  
  之后,我们可以对挑选的模板进行自定义,选择喜欢的样式、文字颜色和排版等。当然也可以安装必要的WordPress插件,比如排版插件Elementer, SEO插件Yoast SEO等
  05
  上传内容
  利用Wordpress后台提供的功能项上传文字、图片和视频即可:
  
  06
  预览&测试网站
  上传了基础页面,产品以及文章内容,我们就可以对网站进行预览,看网站实现的展示效果是否是我们想要的。以及想要的的功能能否全部实现。如果预览测试合格,那么就可以大规模的上传产品和文章内容,并实施SEO优化。
  
  如果功能实现不理想的话,就需要对网站进行调整、修改。
  07
  发布网站&进行营销工作
  确保我们的网站没有问题了,我们就可以发布网站,让谷歌对网站进行收录。并安排之后的网站营销工作,比如SEO优化,谷歌广告或者是社交引流等.
  如果大家对于如何选择建站系统有任何的疑问,欢迎大家在下方进行留言。
  END
  想要学习更多外贸SEO知识,可以通过以下方式找到我们:
   查看全部

  跨境电商从0到100:企业该如何选择建站系统
  
  写在前面的话:
  最近跨境圈可谓风起云涌,亚马逊众多头部玩家纷纷暴雷:全部店铺账号被封,几亿甚至是几十亿的资产被套牢,员工晚上打卡,第二天收到企业遣散通知……亚马逊卖家人人自危。
  
  这个时候,大家也都意识到了,拥有自主话语权的网站和品牌是多么的重要。因此独立站成为新的跨境风口。但风口里面也会有砂砾甚至是石头,你碰到了不会死但是可能会受伤或者让你难受一下。在独立站建设过程中,部分人也会遇到一些大坑或者是不靠谱的人,所以我们推出了从独立站到品牌营销系列。帮助大家在认知上了解独立站从建站到优化过程中所涉及的问题以及解决方案,希望可以帮助大家少踩一些坑。大家可以通过链接观看之前的几篇文章:今天要给大家分享的是企业该如何选择建站系统。
  Part 1、常见的建站系统
  市面上常见的建站系统,有两种:传统建站和CMS建站系统
  传统建站
  传统建站,顾名思义,最传统的利用代码建站的方式。利用代码建站是所有建站系统的基础。
  
  但是对于没有代码基础的人来说,这种建站方式难度太高,且后期的修改、操作只能是依靠专业的技术人员,可操控性不强。因此也就衍生出了CMS建站系统。
  CMS建站系统
  CMS,是content management system的缩写,即内容管理系统,是一种用来创建内容的网页模板。简单点来说,就是技术人员利用代码写出来一套程序,你只需要将内容上传上去,系统可自动的生成相关的网页。
  它允许多位成员同时进行创建、编辑、发布。用户上传的内容会存储在数据库中,并基于网站模板进行显示。
  
  对比传统的建站方式,CMS建站系统具有以下的优势:
  大家耳熟能详的Wordpress和Shopify都属于CMS建站系统。
  那么,接下来我们来看一下国内、国外常见的CMS建站系统有哪些,以及各自的优势所在:
  国内常见的CMS建站系统
  在我国,经常使用到的建站系统有PageAdmin、织梦DEDECMS、帝国系统, PHPCMS系统等不同的CMS系统,那么我们来看一下这些系统都有哪些区别以及优劣势。
  PageAdmin CMS建站系统(⭐️⭐️⭐️⭐️⭐️)
  PageAdmin CMS建站系统()是国内应用最受欢迎的建站系统之一,大部分的外贸网站都是PageAdmin建成的。它的模板丰富、功能强大、可拓展性强,可以轻松的帮你打造一个独具特色的网站,那么我们来盘点一下,该系统的优缺点:
  优点:
  缺点:
  织梦 DEDE CMS(⭐️⭐️)
  织梦也是国内知名的老牌建站系统了,主要是面向中小企业以及个人站长的新闻内容管理平台。但是其原始创作团队解散之后,这一系统已经不再进行更新和维护了,因此我们看到的织梦DEDE CMS的操作后台比较老化。
  
  织梦DEDE CMS的模板较为简单,可拓展性很差,适合没有定制需求的新手来进行操作。其最令人诟病的地方就是网站的安全性方面,因为织梦是开源的,所以DEDE做的站经常被黑,这个已经是众所周知的事情。
  优点:
  缺点:
  帝国CMS(⭐️⭐️⭐️)
  
  帝国CMS建站系统()是2002年推出的一款CMS建站系统,系统采用老式的表格布局模式,后台非常的复杂,因此对于新手来说不友好。但是其模板标签拓展灵活,但是需要用户有一定的代码基础。
  优点:
  缺点:
  PHPCMS(⭐️⭐️)
  
  PHPCMS适合用来进行二次开发,它的系统底层架构做得不错,承载也很强大,但是需要开发者掌握Html ,PHP, Mysql等技术语言。技术采用模块化方式开发,功能易用便于扩展,采用mvc模式,技术相对其他cms来说,算新的。可惜的是phpcms在2020年初已经关站倒闭。建议大家谨慎选择。
  优点:
  缺点:
  以上的这些就是企业站经常使用到的国内的建站系统。除了这些系统以外,还有一些专门建站博客或者是新闻网站的建站程序,这里大家可以参考一下:
  国外常见的CMS建站系统
  说到国外的CMS建站系统,Wordpress, Shopify, Magento, Bigcommerce等系统都是大家耳熟能详的建站系统,除此以外,还有其他一些在国外比较常用,但是国内很少用到的系统,比如Joomla,Durpal, Sharepoint等。在这里我们来看一下这些网站的优劣势:
  Wordpress建站系统(⭐️⭐️⭐️⭐️⭐️)
  
  Wordpress系统是全球使用最广泛的开源CMS建站系统, 互联网上35%的网站是由WordPress系统建设而成。该平台是在2003年推出,此后凭借简单易上手的操作后台,丰富的模板和插件、良好的拓展性,使其在众多的CMS建站系统中脱颖而出。
  优点:
  缺点:
  Shopify建站系统(⭐️⭐️⭐️⭐️)
  Shopify是一个托管电子商务平台,专门用来建设在线零售商店。这一系统非常适合新手网上开店,无需购买任何主机、管理备份和安全,只需要支付29-299美金,你就可以使用Shopify系统了。
  
  除了最基础的版本, Shopify还推出了每月2000美金的Shopify Plus计划, 与之相对应的是更全面的功能:专属的客户经理、更多的主题和App选择、产品页面支持AR, Video, 3D视频、同一面板同时管理多个Shopify店铺, 更加细致的数据分析功能以及优化完善后的支付系统等。
  优点:
  缺点:
  Magento(⭐️⭐️⭐️⭐️)
  
  Magento是 Adobe 旗下的电子商务平台,可以为精通代码技术的店主提供无限可能。Magento提供两个版本的建站系统: Magento Open Source 和 Magento Commerce.
  使用Magento Open Source,你可以下载一个免费的开源建站系统
  那么 Magento Commerce就是专门针对商业方面的建站了,收费比较昂贵。
  优点:
  缺点:
  Bigcommerce(⭐️⭐️⭐️⭐️)
  Bigcommerce是一个一体化的在线电子商务平台,它的性质和Shopify差不多。如果你对代码一窍不通,那么这个平台的话,很适合你。
  
  Bigcommerce平台是收费的,但是你可以免费试用。因为平台是一站式的管理系统,所以不需要额外的购买服务器、域名(域名平台可以免费提供,类似于,当然你也可以自行购买)。
  平台提供丰富的模板和插件,可以实现高度的自定义设计。因为主要为电子商务设计,所以可以在不影响速度的前提下,上传大量的产品、图片和文章。后台操作界面非常的清晰,简单,适合新手操作。
  优点:
  缺点:
  Joomla(⭐️⭐️⭐️)
  
  Joomla也是一个免费的开源CMS建站系统。平台成立于2005年。它和Wordpress一样,已经发展了很多年,而且平台中模板和插件非常的丰富,可拓展性非常的强。对比其他的建站系统,Joomla拥有更强大的内置功能。依靠其内置功能,用户可以轻松的使用多语言创建页面,以及创建不同模板和类型的文章页面等。但是在国内的话,很少有企业使用这一系统,因此相关的技术人员也很难找到。
  优点:
  缺点:
  Drupal(⭐️⭐️⭐️)
  Drupal也是一个开源的CMS系统,可以用来创建大型网站、个人博客和新闻网站等。由于该平台是专门为研发人员进行设计的,所以使用者必须要对 PHP、HTML 和 CSS 有一定的了解才能充分的利用Drupal的全部功能。
  
  Drupal CMS建站功能拥有数千个模板和插件可供选择,可实现高度的自定义设计功能。多语言功能内置到系统中,可以轻松实现多语言切换。另外,其安全性也是所有的CMS建站系统中首屈一指的。
  优点:
  缺点:
  Part2、外贸企业挑选建站系统注意事项
  上面我们盘点了那么多的建站系统,那么我们该选择哪一个呢?在选择之前,建议大家从以下的角度来进行考量
  1、系统的易用性
  优秀的CMS系统,可以让你非常简单轻松的就能上传、编辑管理你的内容。这种系统的后台一般都支持拖放功能,可以让你在页面中添加不同的模块和元素。
  2、系统功能完善、成熟度高、用户量大
  只有系统功能完善的CMS系统才能实现你对网站的所有设想。如果系统不完善,不成熟的话,会导致功能无法实现,影响网站的建设。系统功能完善,成熟度高、用户量大、这样的系统才有较高的实用性,满足企业的基础功能需求,利于后期自行维护
  3、安全性(非常重要!!!)
  CMS系统的安全性是我们需要重点衡量的一个因素,毕竟好不容易建了一个网站,谁都不希望这个网站受到黑客的攻击。所以CMS系统是不是经常进行更新,安装补丁,以及是否有相关的工作人员/社区进行技术上的支持就非常的重要了。除了系统的安全性,我们还要考虑到数据信息的安全性。其中包括流量信息、订单信息、客户信息等。如果这些数据可以被第三方轻易的获取,那么网站的损失就大了。
  4、系统是否是开源系统
  国外的大多数CMS建站系统都是开源系统。开源系统意味着代码向公众进行开放,易用性就会比较高。你可以轻松的在建站公司那边获得网站源代码(国内很多公司自己的系统,是不会提供共源代码给你的,也就意味着你只是租了一个房间,最终的所有的东西都还是建站公司的。)
  5、模板和插件的丰富度
  模板和插件比较多的话,可以提供更高的自由度来修改我们的网站。可拓展性比较强
  6、搜索引擎优化
  CMS系统是否针对搜索引擎进行过优化,以及是否有第三方的插件支持网站进行搜索引擎优化。毕竟网站建了之后就是要在搜索引擎上面做排名的。如果CMS系统对搜索引擎不友好的话,网站建设了意义也不大。
  7、售后以及技术支持
  网站就像一台庞大的机器,当这个机器出问题了,你需要看一下,是不是有足够的技术支持可以帮助你解决这一问题。找不到技术支持,或者解决问题速度太慢,都会影响网站的正常工作。
  结合以上的7种元素,在这里推荐大家使用以下的建站系统进行建站:
  那么接下来,我们以WordPress为例,教给大家如何7步建成独立站。
  Part3、7步建成独立站
  01
  挑选域名
  在建站之前,你要先确定你的网站名称,并购买域名。选择一个合适的域名没有那么简单的。关于如何挑选域名,可参考我们之前的文章-《
  02
  挑选服务器
  关于如何挑选服务器,可参考我们之前的文章-《
  03
  安装Wordpress
  不管你的服务器,挑选的是Siteground, Bluehost, 还是Inmotion Hosting, 这些大的网站后台都集成了WordPress安装,只需要简单的操作即可进行安装,在这里,以Inmotion Hosting为例,
  1、登陆Inmotion Hosting控制面板-cPanel
  2、找到Software板块,点击 Softaculous Apps installer
  
  3、点开后选择Wordpress的标志,点开就能看到安装的界面,点击“install”进行安装
  4、按照要求填写WordPress安装信息
  5、Softaculous Apps installer会检查你填写和提交的数据,并将wordpress文件安装到你的服务器上面。点击返回概览,你会在当前安装列表中看到你的WordPress安装进度。
  
  04
  挑选模板并进行自定义
  网站除了要有优秀的文字内容来吸引用户外,还需要有漂亮的网页设计。Wordpress系统中提供了大量的免费和付费的网站模板可供用户来进行选择,我们只需要点开Wordpress后台Apperance-Themes就可以看到系统提供的免费模板。
  
  点击“Add New" 进入模板库,在模板库里面选择自己心仪的网站模板进行安装并激活就可以应用到网站上面。
  
  除了在worpress模板库里面直接安装模板,我们还可以到第三方网站上面去购买WordPress的模板。很多第三方网站上面的WordPress模板是专业的技术人员进行开发或者是优化过后的,展示效果和优化效果都很好。
  著名的WordPress模板出售网站有以下几个:
  在这些网站上面购买的模板有另外一种方法进行安装:登陆Wordpress后台-点击Apperance-Add New
  进去之后,点击 Upload Theme,将你从第三方网站上购买到的WordPress模板文件.zip上传,激活并安装。
  
  之后,我们可以对挑选的模板进行自定义,选择喜欢的样式、文字颜色和排版等。当然也可以安装必要的WordPress插件,比如排版插件Elementer, SEO插件Yoast SEO等
  05
  上传内容
  利用Wordpress后台提供的功能项上传文字、图片和视频即可:
  
  06
  预览&测试网站
  上传了基础页面,产品以及文章内容,我们就可以对网站进行预览,看网站实现的展示效果是否是我们想要的。以及想要的的功能能否全部实现。如果预览测试合格,那么就可以大规模的上传产品和文章内容,并实施SEO优化。
  
  如果功能实现不理想的话,就需要对网站进行调整、修改。
  07
  发布网站&进行营销工作
  确保我们的网站没有问题了,我们就可以发布网站,让谷歌对网站进行收录。并安排之后的网站营销工作,比如SEO优化,谷歌广告或者是社交引流等.
  如果大家对于如何选择建站系统有任何的疑问,欢迎大家在下方进行留言。
  END
  想要学习更多外贸SEO知识,可以通过以下方式找到我们:
  

Python识别CMS与批量资产收集拓展

网站优化优采云 发表了文章 • 0 个评论 • 99 次浏览 • 2022-06-18 18:53 • 来自相关话题

  Python识别CMS与批量资产收集拓展
  使用模板的话,网站的结构重复度太高,不利于搜索引擎优化
  回归到本文的主旨,在渗透测试中检测目标网址是否基于CMS模板开发,判断使用的CMS类型是非常重要的一步,可以查找网上已曝光的CMS程序漏洞,运气好能一步到位拿到权限,如果该CMS系统开源,还能下载相对应的源码进行代码审计。
  根据个人经验,总结一下识别网站CMS类型的五种方法,本质上都是根据网页内容或者网页文件的特征进行识别。只是根据不同类型的网页大概分成五类,方便理解和阅读,至于在网上找到在线识别CMS网站的接口然后加到爬虫中,省时省力却不在本文的讨论范围之内,当然会在以后视频课程的爬虫专栏会专门讲。
  根据页面内容识别CMS类型
  许多CMS系统会在网站的首页加上一些象征该CMS的关键词,举个例子,WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设自己的网站,如果使用该程序搭建网站,会在该网站的首页出现关键词。下图目标网址案例就是使用WordPress搭建:
  
  我们策略判断该网址是使用WordPress系统搭建的,这样我们识别出来后,就继续确认该网站使用Wordpress的版本号,然后搜索该版本是否出现过相关漏洞,方便下一步渗透测试工作的进行。
  
  那么只需要准备一个指纹库,然后访问目标网站后,对照指纹库的内容,如果命中关键词,则直接判断该网址的CMS类型。
  
  指纹库文件需要不断地收集更新整理,本文中整理好的指纹库获取方式放在文末自取。
  如果使用代码实现,粗略的大体结构大概就是如下设计:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCmsFromBody(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in url_content:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                print('目标网址:{} 识别CMS为:{}'.format(url,v))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except Exception as e:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        print(e)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />CheckCmsFromBody(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  代码粗略功能就是获取首页的内容,然后从指纹库寻找是否出现关键词判定CMS类型。
  根据请求头内容识别CMS类型
  除了上文中从网页内容识别CMS类型,还可以从请求头消息中获取相关信息,某些CMS系统返回的请求头信息中也会添加独特的特征码。如下图目标网站就是使用PowerEasy(动易系统)搭建的网站,可以直接从请求头中获取到特征码,从而判断出使用CMS的类型。
  
  所以在渗透测试的信息收集中,对任何地方都不要放过呀~细心谨慎才能挖到更多的信息。
  这个使用代码实现太简单了,会的同学都懒得看,没有基础的同学看了也看不懂…就不写了…
  主要难点还是在于请求头指纹库的收集与更新。
  
  需要注意的是,请求头是一个字典格式的数据,你需要先把它转换成字符串后,然后再去指纹库寻找特征关键词。
  根据robots.txt文件识别CMS类型
  渗透测试中,robots.txt一定是都会尝试访问的一个文件,robots协议也叫robots.txt是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的哪些文件目录不能访问,哪些可以访问,网站管理员不想让搜索引擎访问的目录是不是含有敏感信息呢?
  答案是的,有些CMS系统会将一些敏感的目录,比如后台管理界面等不允许搜索引擎抓取,也会将一些独特的特征码放入该文件中,以此我们可以根据特征文本关键词进行判定。下图目标网站使用的是PHPCMS v9搭建的系统,通过访问robots文件对比特征码就很容易的识别出使用的CMS类型。
  
  所以还可以根据robots文件的内容方法进行CMS识别。
  根据网站文件md5值识别CMS类型
  MD5指纹(文件指纹验证)当你从网络上下载了软件后,想确保此软件没有被人修改过(如添加了病毒/非官方插件),或在下载中被破坏,可以用文件指纹验证(MD5)技术进行确认。
  原理:
  通过某种算法,对具体的文件进行校验,得出了一个32位的十六进制数(校验和)。待校验文件的文件名和后缀名都可以更改,不影响校核。由于原来的信息只要有稍许改动,通过md5运算后,结果都会有很大的改变。所以,如果再次校验以后所得到的值(md5代码)和此软件发布站或官方网站公布的值不同,就可以认为,文件已被改动过。
  需要注意的是,每个文件对应的MD5的值是不一样的,那么回归到本文主旨,当你使用一套完整的CMS系统的时候,下载了该CMS系统包含的CSS,字体,图标文件,这些文件中有些都是该CMS系统特有的,访问该文件如果该文件存在,然后校验该文件的MD5值,如果与指纹库中一致,则可以判断该网站的CMS类型,该方法相对前面准确率较高。
  指纹库格式是这样:
  网站文件|CMS类型|网站文件的MD5值。<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/static/image/admincp/cloud/qun_op.png|DISCUZ|AB35FA459B0BB01D31BA8FAD0953FCC9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/widget/images/thumbnail.jpg|ECSHOP|7BB50E4281FA02758834A2E9D7BA9FB9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/js/calendar/active-bg.gif|ECSHOP|F8FB9F2B7428C94B41320AA1BC9CF601|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/phpcms/libs/data/font/Vineta.ttf|PHPCMS|E6E557BAD69B09533827D9652E0C11AB|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/statics/images/admin_img/arrowhead-y.png|PHPCMS|6C34F70BD2A05C8C5DDEBB369B5B9509|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  即网站加上网站文件的网址,获取该文件的MD5值,对照指纹库的值是否一致,如果一致则确认该网站使用的CMS类型。python实现识别方式使用代码实现也就四五行,我们假设案例,假设一个指纹库:
  upload/my_girl.jpg|HEXO|587c7132e6043a1de24e03ededa8980d<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  然后使用代码实践进行识别:
  import hashlib,requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />URL = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />req = requests.get(url=URL+'/upload/my_girl.jpg')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5.update(req.content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if md5.hexdigest() == '587c7132e6043a1de24e03ededa8980d':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print('目标网址CMS类型为:HEXO')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试代码结果如下:
  
  根据指定网页内容识别CMS类型
  此类方法结合了上面几种情况下的指纹库,即CMS系统中默认包含一些网页或者文本,这些文本在你搭建好系统后任然存在,你访问这些网页或者文本,然后查看网页文本中是否存在特定的关键词,如果存在就确认CMS类型。
  如下文目标网址使用EmpireCMS(帝国网站管理系统)搭建,访问该网站的:
  e/admin/adminstyle/1/page/about.htm<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  文件,发现该页面存在,然后命中关键词,得出结果该网址使用的帝国网站管理系统搭建而成。
  字典中触发关键词识别,判定为帝国网址管理系统。
  
  补充说明
  除了上面五种访问不同文件类型,然后根据指纹库判定CMS类型,有些时候还可以通过访问错误页面获取信息,这时候可能会遇到防火墙阻拦。
  或者有些网站会对目录做一些修改,可以根据实际情况修改扫描代码,自定义添加二级目录扫描对照指纹库有时候也能发现很多敏感信息。
  上面五种方法中,按照准确率由高到低排序为:
  MD5值校验识别>指定网页内容识别>Robots.txt文件识别>请求头信息识别>首页内容识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  按照扫描需要的时间由低到高排序为:
  首页内容识别=请求头信息识别=Robots.txt文件识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  因为首页内容识别、请求头信息识别、Robots.txt文件识别只用访问一次该网站,不会产生大量的扫描,成功与否主要取决于你的指纹库。如果要扫描指定网页内容和校验MD5值,则会产生较多甚至大量的访问扫描,很容易触发防火墙引起很多麻烦事情上身,当然这些都可以通过降低扫描频率、自动随机切换代理IP、分布式低频率扫描等多种手段绕过。
  回归到本文主旨,识别CMS类型最最重要还得依赖强大的指纹库,甚至可以说完全依赖于指纹库的数据,五种方法只是思路的一个分类,能不能产出结果还是要靠指纹库的,关于如何更新整理指纹库,可以在GitHub上收集整理,各大论坛也有好心人专门整理,当然你也可以自己下载多套CMS系统,然后自己分析哪些文件是CMS独有的,校验出MD5值或者考察关键词等等清洗数据后加入更新到你的指纹库。
  Python识别CMS代码工程设计实现与拓展
  虽然整个工程看上去很多东西挺复杂,但是仔细去分析各个功能模块就会发现很容易实现,你需要做的就是把每个功能单独完成后,整体搭建在一起形成一套流程即可。下面演示代码为大致流程,方便阅读理解。
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  所以只需要访问一次网址的首页,拿到首页内容和请求头信息先对比,访问robots.txt文件检测,最后扫描指定网页内容检测关键词和验证MD5值。
  具体流程图:
  
  代码实现如下:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 指纹库信息,因为我收集了差不多5000条指纹,如果全部放在代码中,则文章就写不下了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 本代码仅作演示案例的工程结构<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 关于优化以及拓展,详细会在文章中介绍<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 首页内容指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 请求头信息指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># robots文件指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># MD5指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 特定网页指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 最后根据MD5值判定,其实如果前面都没有判定出来的话,这里扫描的意义也不是很大<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in cms_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_s = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_s)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5.update(res[1])<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            rmd5 = md5.hexdigest()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 == rmd5:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if __name__ == '__main__':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print(CheckCMS(url))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试结果:
  以上大致就是使用代码识别CMS类型的流程,有代码基础的同学可以自己进行拓展,举几个例子:
  加入WAF识别功能,即调用特定网页内容鉴定和MD5值校验之前,启动WAF识别,如果发现存在WAF就自行跳过,关于WAF识别的代码在公众号上两篇文章有源代码
  加入随机请求头,随机代理IP等条件,伪装成浏览器
  对网站的目录进行爬行,然后抓取爬行网页的内容对比参照指纹库关键词,有些时候也能命中不少,因为一些关键词不一定出现在首页,也有可能出现在错误页面或者404页面中
  引入线程池,实现批量扫描网址然后识别CMS类型后保存在文本,同样可以实现批量刷洞的效果,不过这种做法有涉及到HC的嫌疑,所以如果不是业务需求还是不要去做
  寻找多个在线识别CMS的接口,然后写个爬虫,结合在一起识别,当然这个如果作为长期使用的话,还得定期检查接口是否有效
  单单仅凭靠首页内容关键词判定CMS类型,其实是存在较大的误报率,可以结合robots文件等一起结合判断
  可以结合其他知识点做出有意思的东西,主要是要把自己的思维拓展开,比如结合Flask做一个简易版在线版识别CMS,也就十几行代码。一时手痒写一个,图个乐吧大家….
  代码如下:
  # coding:utf-8<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />from flask import Flask,request<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />app = Flask(__name__)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit ! 查看全部

  Python识别CMS与批量资产收集拓展
  使用模板的话,网站的结构重复度太高,不利于搜索引擎优化
  回归到本文的主旨,在渗透测试中检测目标网址是否基于CMS模板开发,判断使用的CMS类型是非常重要的一步,可以查找网上已曝光的CMS程序漏洞,运气好能一步到位拿到权限,如果该CMS系统开源,还能下载相对应的源码进行代码审计。
  根据个人经验,总结一下识别网站CMS类型的五种方法,本质上都是根据网页内容或者网页文件的特征进行识别。只是根据不同类型的网页大概分成五类,方便理解和阅读,至于在网上找到在线识别CMS网站的接口然后加到爬虫中,省时省力却不在本文的讨论范围之内,当然会在以后视频课程的爬虫专栏会专门讲。
  根据页面内容识别CMS类型
  许多CMS系统会在网站的首页加上一些象征该CMS的关键词,举个例子,WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设自己的网站,如果使用该程序搭建网站,会在该网站的首页出现关键词。下图目标网址案例就是使用WordPress搭建:
  
  我们策略判断该网址是使用WordPress系统搭建的,这样我们识别出来后,就继续确认该网站使用Wordpress的版本号,然后搜索该版本是否出现过相关漏洞,方便下一步渗透测试工作的进行。
  
  那么只需要准备一个指纹库,然后访问目标网站后,对照指纹库的内容,如果命中关键词,则直接判断该网址的CMS类型。
  
  指纹库文件需要不断地收集更新整理,本文中整理好的指纹库获取方式放在文末自取。
  如果使用代码实现,粗略的大体结构大概就是如下设计:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCmsFromBody(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in url_content:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                print('目标网址:{} 识别CMS为:{}'.format(url,v))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except Exception as e:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        print(e)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />CheckCmsFromBody(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  代码粗略功能就是获取首页的内容,然后从指纹库寻找是否出现关键词判定CMS类型。
  根据请求头内容识别CMS类型
  除了上文中从网页内容识别CMS类型,还可以从请求头消息中获取相关信息,某些CMS系统返回的请求头信息中也会添加独特的特征码。如下图目标网站就是使用PowerEasy(动易系统)搭建的网站,可以直接从请求头中获取到特征码,从而判断出使用CMS的类型。
  
  所以在渗透测试的信息收集中,对任何地方都不要放过呀~细心谨慎才能挖到更多的信息。
  这个使用代码实现太简单了,会的同学都懒得看,没有基础的同学看了也看不懂…就不写了…
  主要难点还是在于请求头指纹库的收集与更新。
  
  需要注意的是,请求头是一个字典格式的数据,你需要先把它转换成字符串后,然后再去指纹库寻找特征关键词。
  根据robots.txt文件识别CMS类型
  渗透测试中,robots.txt一定是都会尝试访问的一个文件,robots协议也叫robots.txt是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的哪些文件目录不能访问,哪些可以访问,网站管理员不想让搜索引擎访问的目录是不是含有敏感信息呢?
  答案是的,有些CMS系统会将一些敏感的目录,比如后台管理界面等不允许搜索引擎抓取,也会将一些独特的特征码放入该文件中,以此我们可以根据特征文本关键词进行判定。下图目标网站使用的是PHPCMS v9搭建的系统,通过访问robots文件对比特征码就很容易的识别出使用的CMS类型。
  
  所以还可以根据robots文件的内容方法进行CMS识别。
  根据网站文件md5值识别CMS类型
  MD5指纹(文件指纹验证)当你从网络上下载了软件后,想确保此软件没有被人修改过(如添加了病毒/非官方插件),或在下载中被破坏,可以用文件指纹验证(MD5)技术进行确认。
  原理:
  通过某种算法,对具体的文件进行校验,得出了一个32位的十六进制数(校验和)。待校验文件的文件名和后缀名都可以更改,不影响校核。由于原来的信息只要有稍许改动,通过md5运算后,结果都会有很大的改变。所以,如果再次校验以后所得到的值(md5代码)和此软件发布站或官方网站公布的值不同,就可以认为,文件已被改动过。
  需要注意的是,每个文件对应的MD5的值是不一样的,那么回归到本文主旨,当你使用一套完整的CMS系统的时候,下载了该CMS系统包含的CSS,字体,图标文件,这些文件中有些都是该CMS系统特有的,访问该文件如果该文件存在,然后校验该文件的MD5值,如果与指纹库中一致,则可以判断该网站的CMS类型,该方法相对前面准确率较高。
  指纹库格式是这样:
  网站文件|CMS类型|网站文件的MD5值。<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/static/image/admincp/cloud/qun_op.png|DISCUZ|AB35FA459B0BB01D31BA8FAD0953FCC9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/widget/images/thumbnail.jpg|ECSHOP|7BB50E4281FA02758834A2E9D7BA9FB9|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/js/calendar/active-bg.gif|ECSHOP|F8FB9F2B7428C94B41320AA1BC9CF601|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/phpcms/libs/data/font/Vineta.ttf|PHPCMS|E6E557BAD69B09533827D9652E0C11AB|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />/statics/images/admin_img/arrowhead-y.png|PHPCMS|6C34F70BD2A05C8C5DDEBB369B5B9509|<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  即网站加上网站文件的网址,获取该文件的MD5值,对照指纹库的值是否一致,如果一致则确认该网站使用的CMS类型。python实现识别方式使用代码实现也就四五行,我们假设案例,假设一个指纹库:
  upload/my_girl.jpg|HEXO|587c7132e6043a1de24e03ededa8980d<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  然后使用代码实践进行识别:
  import hashlib,requests<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />URL = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />req = requests.get(url=URL+'/upload/my_girl.jpg')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />md5.update(req.content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if md5.hexdigest() == '587c7132e6043a1de24e03ededa8980d':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print('目标网址CMS类型为:HEXO')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试代码结果如下:
  
  根据指定网页内容识别CMS类型
  此类方法结合了上面几种情况下的指纹库,即CMS系统中默认包含一些网页或者文本,这些文本在你搭建好系统后任然存在,你访问这些网页或者文本,然后查看网页文本中是否存在特定的关键词,如果存在就确认CMS类型。
  如下文目标网址使用EmpireCMS(帝国网站管理系统)搭建,访问该网站的:
  e/admin/adminstyle/1/page/about.htm<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  文件,发现该页面存在,然后命中关键词,得出结果该网址使用的帝国网站管理系统搭建而成。
  字典中触发关键词识别,判定为帝国网址管理系统。
  
  补充说明
  除了上面五种访问不同文件类型,然后根据指纹库判定CMS类型,有些时候还可以通过访问错误页面获取信息,这时候可能会遇到防火墙阻拦。
  或者有些网站会对目录做一些修改,可以根据实际情况修改扫描代码,自定义添加二级目录扫描对照指纹库有时候也能发现很多敏感信息。
  上面五种方法中,按照准确率由高到低排序为:
  MD5值校验识别>指定网页内容识别>Robots.txt文件识别>请求头信息识别>首页内容识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  按照扫描需要的时间由低到高排序为:
  首页内容识别=请求头信息识别=Robots.txt文件识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  因为首页内容识别、请求头信息识别、Robots.txt文件识别只用访问一次该网站,不会产生大量的扫描,成功与否主要取决于你的指纹库。如果要扫描指定网页内容和校验MD5值,则会产生较多甚至大量的访问扫描,很容易触发防火墙引起很多麻烦事情上身,当然这些都可以通过降低扫描频率、自动随机切换代理IP、分布式低频率扫描等多种手段绕过。
  回归到本文主旨,识别CMS类型最最重要还得依赖强大的指纹库,甚至可以说完全依赖于指纹库的数据,五种方法只是思路的一个分类,能不能产出结果还是要靠指纹库的,关于如何更新整理指纹库,可以在GitHub上收集整理,各大论坛也有好心人专门整理,当然你也可以自己下载多套CMS系统,然后自己分析哪些文件是CMS独有的,校验出MD5值或者考察关键词等等清洗数据后加入更新到你的指纹库。
  Python识别CMS代码工程设计实现与拓展
  虽然整个工程看上去很多东西挺复杂,但是仔细去分析各个功能模块就会发现很容易实现,你需要做的就是把每个功能单独完成后,整体搭建在一起形成一套流程即可。下面演示代码为大致流程,方便阅读理解。
  综合性价比由高到低排序为:
  Robots.txt文件识别>请求头信息识别>首页内容识别>指定网页内容识别>MD5值校验识别<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  所以只需要访问一次网址的首页,拿到首页内容和请求头信息先对比,访问robots.txt文件检测,最后扫描指定网页内容检测关键词和验证MD5值。
  具体流程图:
  
  代码实现如下:
  # -*- coding:utf-8 -*-<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 指纹库信息,因为我收集了差不多5000条指纹,如果全部放在代码中,则文章就写不下了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 本代码仅作演示案例的工程结构<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 关于优化以及拓展,详细会在文章中介绍<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 首页内容指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 请求头信息指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># robots文件指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># MD5指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /># 特定网页指纹库<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 最后根据MD5值判定,其实如果前面都没有判定出来的话,这里扫描的意义也不是很大<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in cms_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_s = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_s)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5 = hashlib.md5()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            md5.update(res[1])<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            rmd5 = md5.hexdigest()<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 == rmd5:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, cms_name)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />if __name__ == '__main__':<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url = 'http://www.langzi.fun'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    print(CheckCMS(url))<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />
  测试结果:
  以上大致就是使用代码识别CMS类型的流程,有代码基础的同学可以自己进行拓展,举几个例子:
  加入WAF识别功能,即调用特定网页内容鉴定和MD5值校验之前,启动WAF识别,如果发现存在WAF就自行跳过,关于WAF识别的代码在公众号上两篇文章有源代码
  加入随机请求头,随机代理IP等条件,伪装成浏览器
  对网站的目录进行爬行,然后抓取爬行网页的内容对比参照指纹库关键词,有些时候也能命中不少,因为一些关键词不一定出现在首页,也有可能出现在错误页面或者404页面中
  引入线程池,实现批量扫描网址然后识别CMS类型后保存在文本,同样可以实现批量刷洞的效果,不过这种做法有涉及到HC的嫌疑,所以如果不是业务需求还是不要去做
  寻找多个在线识别CMS的接口,然后写个爬虫,结合在一起识别,当然这个如果作为长期使用的话,还得定期检查接口是否有效
  单单仅凭靠首页内容关键词判定CMS类型,其实是存在较大的误报率,可以结合robots文件等一起结合判断
  可以结合其他知识点做出有意思的东西,主要是要把自己的思维拓展开,比如结合Flask做一个简易版在线版识别CMS,也就十几行代码。一时手痒写一个,图个乐吧大家….
  代码如下:
  # coding:utf-8<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />from flask import Flask,request<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />import requests,hashlib<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />app = Flask(__name__)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body = {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'content="WordPress':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'wp-includes':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'pma_password':'phpMyAdmin',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'hexo':'hexo',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'TUTUCMS':'tutucms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Powered by TUTUCMS':'tutucms',  'Powered by 1024 CMS':'1024 CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'Discuz':'Discuz',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '1024 CMS (c)':'1024 CMS',  'Publish By JCms2010':'捷点 JCMS',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />head = {'X-Pingback':'WordPress',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'xmlrpc.php':'WordPress',  'wordpress_test_cookie':'WordPress',  'phpMyAdmin=':'phpMyAdmin=',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'adaptcms':'adaptcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'SS_MID&squarespace.net':'squarespace建站',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Mas-Server':'TRS MAS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'dr_ci_session':'dayrui系列CMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'http://www.cmseasy.cn/service_1.html':'CmsEasy',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Osclass':'Osclass',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'clientlanguage':'unknown cms rcms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'X-Powered-Cms: Twilight CMS':'TwilightCMS',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'IRe.CMS':'irecms',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DotNetNukeAnonymous':'DotNetNuke',}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />robots = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'Tncms', '新为软件E-learning管理系统', '贷齐乐系统', '中企动力CMS', '全国烟草系统', 'Glassfish', 'phpvod', 'jieqi', '老Y文章管理系统',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> 'DedeCMS']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />cms_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/admina/sitmap0.png|08cms|e0c4b6301b769d596d183fa9688b002a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/install/images/logo.gif|建站之星|ac85215d71732d34af35a8e69c8ba9a2|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/jiaowu/hlp/Images/node.gif|qzdatasoft强智教务管理系统|70ee6179b7e3a5424b5ca22d9ea7d200|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/themes/README.txt|drupal|5954fc62ae964539bb3586a1e4cb172a|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/view/resource/skin/skin.txt|未知政府采购系统|61a9910d6156bb5b21009ba173da0919|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/theme/admin/images/upload.gif|sdcms|d5cd0c796cd7725beacb36ebd0596190|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/images/logout/topbg.jpg|TurboMail邮箱系统|f6d7a10b8fe70c449a77f424bc626680|',]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />body_rule = [<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/robots.txt|EmpireCMS|EmpireCMS|', '/images/css.css.lnk|KesionCMS(科讯)|kesioncms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/data/flashdata/default/cycle_image.xml|ecshop|ecshop|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/admin/SouthidcEditor/Include/Editor.js|良精|southidc|', '/plugin/qqconnect/bind.html|PHP168(国徽)|php168|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/SiteServer/Themes/Language/en.xml|SiteServer|siteserver|', '/system/images/fun.js|KingCMS|kingcms|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/INSTALL.mysql.txt|Drupal(水滴)|drupal|', '/themes/default/style.css|ecshop|ECSHOP|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /> '/hack/gather/template/addrulesql.htm|qiboSoft(齐博)|qiboSoft|',<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />'/phpcms/templates/default/wap/header.html|phpcms|phpcms']<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def GetContent(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    这个函数功能是:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        接受一个传入的网址,返回传入网址的  (请求头信息,原始网页数据,解码成中文后的网页内容)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        当然前提是访问成功了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        如果访问失败,则直接返回None了<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    '''<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    try:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        r = requests.get(url,timeout=5,headers=headers)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        encoding = requests.utils.get_encodings_from_content(r.text)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_content = r.content.decode(encoding, 'replace')<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        return (str(r.headers),r.content,url_content)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    except:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        pass<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />def CheckCMS(url):<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 根据robots文件判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    url_r = url+'/robots.txt'<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url_r)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for robot in robots:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if robot in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, robot)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据 网页内容和请求头信息判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    res = GetContent(url)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in head.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[0]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url,v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        for k,v in body.items():<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if k in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />                return '{}-->CMS类型为:{}'.format(url, v)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    # 然后根据特定网址的内容判定<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    for x in body_rule:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_prefix = x.split('|', 3)[0]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_name = x.split('|', 3)[1]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        cms_md5 = x.split('|', 3)[2]<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        url_c = url + cms_prefix<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        res = GetContent(url_c)<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        if res != None:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />            if cms_md5 in res[2]:<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !

cms+php/oc,二次开发,网站设计模板

网站优化优采云 发表了文章 • 0 个评论 • 68 次浏览 • 2022-06-03 06:07 • 来自相关话题

  cms+php/oc,二次开发,网站设计模板
  cms网站后台内容管理系统模板开发,cms网站后台模板制作saas/cms培训/代码,数据库,工程开发网站功能区域划分图phpcms基础编程saas产品集成wap/seh5,app开发源码/模板/页面/模板,数据库,工程开发前端一键代码生成神马修phpcms,cms,cms网站二次开发/saas/cms产品开发,代码二次开发开源产品代码库提供给大家,节省了时间,增加了我们产品的价值,将来可以更方便大家。
  asp+php/oc/php,二次开发,网站设计模板推荐工具3c875ba817,3c875ba817二次开发是一个帮助网站开发者快速掌握各种小系统二次开发的实用工具箱提供开发效率,减少网站开发时间,减少维护工作量。还提供各种二次开发机制,云开发技术,等技术支持,方便大家开发出有价值的产品。工具箱功能区域划分图非常详细的工具箱图,大家根据需要自行对比筛选。
  phpcms源码下载、代码生成工具4loodway+simpleweb——仅需2分钟使用saas工具最为方便,节省的时间就是生命。代码模板化代码使用格式化的代码生成器生成,模板更加新颖。代码自动化开发全自动代码开发,按照我们写的代码生成器生成代码,变动维护非常方便,操作熟练后可以把自己生成的代码定制成一个自己专用的项目。
  大家可以自行体验,生成的代码一个是商城,一个是旅游。cms开发培训,cms网站后台模板制作,cms程序开发,cms开发的网站很多,很多网站会要求程序要有多少程序员,如果有很多人并没有做好开发工作,公司可能根本无法正常运转下去。很多公司是代码团队,但是项目开发周期又很紧迫,无法找到程序员帮助开发,这个时候往往会使用第三方的cms,如云开发,我们也不例外。
  5代码进度管理,phpcms多人开发开发进度管理phpcms自定义rd人员开发管理,rd员工进度管理。公司招聘也可以使用代码自动化开发。6代码文件管理,phpcms代码rd多代码。分批次编译代码,代码自动化生成。7存储系统自动化更新不用找人手动更新代码,自动化编译,自动化发布到各个存储系统如cvs/git/svn/metis/apowk等等自动化更新。
  自动化修改错误代码等自动化管理工具8开发质量管理多代码库,大部分程序不用重新编译。根据你的需求开发的多代码。结语:phpcms企业用户使用规范-4l。 查看全部

  cms+php/oc,二次开发,网站设计模板
  cms网站后台内容管理系统模板开发,cms网站后台模板制作saas/cms培训/代码,数据库,工程开发网站功能区域划分图phpcms基础编程saas产品集成wap/seh5,app开发源码/模板/页面/模板,数据库,工程开发前端一键代码生成神马修phpcms,cms,cms网站二次开发/saas/cms产品开发,代码二次开发开源产品代码库提供给大家,节省了时间,增加了我们产品的价值,将来可以更方便大家。
  asp+php/oc/php,二次开发,网站设计模板推荐工具3c875ba817,3c875ba817二次开发是一个帮助网站开发者快速掌握各种小系统二次开发的实用工具箱提供开发效率,减少网站开发时间,减少维护工作量。还提供各种二次开发机制,云开发技术,等技术支持,方便大家开发出有价值的产品。工具箱功能区域划分图非常详细的工具箱图,大家根据需要自行对比筛选。
  phpcms源码下载、代码生成工具4loodway+simpleweb——仅需2分钟使用saas工具最为方便,节省的时间就是生命。代码模板化代码使用格式化的代码生成器生成,模板更加新颖。代码自动化开发全自动代码开发,按照我们写的代码生成器生成代码,变动维护非常方便,操作熟练后可以把自己生成的代码定制成一个自己专用的项目。
  大家可以自行体验,生成的代码一个是商城,一个是旅游。cms开发培训,cms网站后台模板制作,cms程序开发,cms开发的网站很多,很多网站会要求程序要有多少程序员,如果有很多人并没有做好开发工作,公司可能根本无法正常运转下去。很多公司是代码团队,但是项目开发周期又很紧迫,无法找到程序员帮助开发,这个时候往往会使用第三方的cms,如云开发,我们也不例外。
  5代码进度管理,phpcms多人开发开发进度管理phpcms自定义rd人员开发管理,rd员工进度管理。公司招聘也可以使用代码自动化开发。6代码文件管理,phpcms代码rd多代码。分批次编译代码,代码自动化生成。7存储系统自动化更新不用找人手动更新代码,自动化编译,自动化发布到各个存储系统如cvs/git/svn/metis/apowk等等自动化更新。
  自动化修改错误代码等自动化管理工具8开发质量管理多代码库,大部分程序不用重新编译。根据你的需求开发的多代码。结语:phpcms企业用户使用规范-4l。

自定义用于 Web 开发的开源 PHP 框架 Codeigniter | Lin

网站优化优采云 发表了文章 • 0 个评论 • 104 次浏览 • 2022-05-31 21:29 • 来自相关话题

  自定义用于 Web 开发的开源 PHP 框架 Codeigniter | Lin
  译者:geekpi
  PHP Codeigniter 是一个开源框架,为商业应用提供易于使用的 PHP 编程语言和强大的编码工具。它还提供商务智能、服务器监视、开发和应用集成功能。这是一个相对冷清的项目,你很少听到它,但它功能强大,许多刚接触的开发人员都对此感到惊讶和耳目一新。
  我在新加坡的一家在线学习服务提供商处使用Codeigniter。我们提供的服务并不算常见,没有可以作为模板的默认功能集或现有后台管理系统,所以我需要一个能提供良好的、可靠的、可以建立在此基础上的原始材料。最初,我考虑用其他平台(如 Wordpress)用于我们的网站。但是,我决定使用 Codeigniter,因为它的灵活性,以及集成了在我们的补课匹配过程中需要的功能。
  以下是打动我使用 Codeigniter 的原因:
  ◈与 MySQL 数据库的集成 —— 主要功能是允许客户端浏览导师的数据库并添加导师,例如类似于电子商务平台的“购物车”。◈客户端界面系统 —— 用户可以登录来管理偏好并编辑详细信息,修改所教的科目、旅游的地区、手机号码、地址等。◈定制的管理员面板 —— 管理员可以使用定制的管理面板访问客户提交的资料,它与客户服务功能集成在一起,因此管理员可以单独跟进。◈付款系统 —— 管理面板带有与 Paypal 集成的发票和付款网关。◈ CMS 编辑器界面 —— 管理员能够编辑博客和文章中的文本和图像,以及添加新页面。
  该项目花费了大约六个月的时间来完成,另外花了两个月的调试时间。如果我需要从头开始构建所有,或者尝试重新设计现有的框架以满足我们的需求,那将花费更长的时间,而且可能最终无法满足客户需求。
  
  功能和优点
  PHP Codeigniter还有很多吸引开发者的功能,包括错误处理和代码格式化,这些功能在各种编码情景下都非常有用。它支持模板,可用于向现有网站添加功能或生成新网站。有许多基于 web 系统商业需要的功能,包括使用自定义标签。即使没有编程经验的普通开发人员也可以使用大多数工具。
  Codeigniter 的主要功能是:
  ◈XML 核心服务,◈HTTP/FTP 核心服务◈AppData 和 PHP 沙箱功能◈XSLT 和 HTML 模板◈加密的信息传输◈PCM Codeigniter 服务器监控◈应用集成◈文件传输协议(FTP)◈服务台支持◈Apache POI(用于托管网站的内容管理基础架构)
  
  兼容性
  Codeigniter 与许多领先的软件程序兼容,例如 PHP、MySQL、MariaDB、phpMyAdmin、Apache、OpenBSD、XSLT、SQLite等。许多公司更喜欢使用 Codeigniter 产品来满足网站要求,因为它们易于使用和集成。如果你不想创建自己的网站,你可以找到许多提供自定义 Web 开发服务的开发人员和设计机构。
  
  安全
  Codeigniter 还通过 SSL 加密提供数据安全性。加密可以保护数据免受入侵者和防火墙外部威胁的侵害。数据存储功能还允许对公司网站进行安全审核。
  
  其它功能
  一家优秀的 PHP Web 开发公司会使用几种高级技术和第三方技术,例如 XML 和 PHP。它为企业提供了一个完整的平台,可以开发出具有看起来专业的、好用的商业网站。Codeigniter 使得第三方技术的使用变得容易,并可以与常见的 Web 开发软件一起使用。这使得 Web 公司可以轻松地使用所选模块创建网站。大多数 PHP 开发者也为个人提供支持和培训服务。
  
  使用 PHP 框架 Codeigniter
  Codeigniter 给企业提供了完整的 PHP 开发包,它将提供强大的功能、灵活性和性能完美结合在一起。到目前为止,我很满意我们的网站,并不断地升级和添加新的功能。并不断升级和增加新的功能。我期待着发现我们的网站还能用 Codeigniter 做些什么。你也是这样么?
  via:
  作者:Wee Ben Sen选题:lujun9972译者:geekpi校对:wxy
  本文由LCTT原创编译,Linux中国荣誉推出
   查看全部

  自定义用于 Web 开发的开源 PHP 框架 Codeigniter | Lin
  译者:geekpi
  PHP Codeigniter 是一个开源框架,为商业应用提供易于使用的 PHP 编程语言和强大的编码工具。它还提供商务智能、服务器监视、开发和应用集成功能。这是一个相对冷清的项目,你很少听到它,但它功能强大,许多刚接触的开发人员都对此感到惊讶和耳目一新。
  我在新加坡的一家在线学习服务提供商处使用Codeigniter。我们提供的服务并不算常见,没有可以作为模板的默认功能集或现有后台管理系统,所以我需要一个能提供良好的、可靠的、可以建立在此基础上的原始材料。最初,我考虑用其他平台(如 Wordpress)用于我们的网站。但是,我决定使用 Codeigniter,因为它的灵活性,以及集成了在我们的补课匹配过程中需要的功能。
  以下是打动我使用 Codeigniter 的原因:
  ◈与 MySQL 数据库的集成 —— 主要功能是允许客户端浏览导师的数据库并添加导师,例如类似于电子商务平台的“购物车”。◈客户端界面系统 —— 用户可以登录来管理偏好并编辑详细信息,修改所教的科目、旅游的地区、手机号码、地址等。◈定制的管理员面板 —— 管理员可以使用定制的管理面板访问客户提交的资料,它与客户服务功能集成在一起,因此管理员可以单独跟进。◈付款系统 —— 管理面板带有与 Paypal 集成的发票和付款网关。◈ CMS 编辑器界面 —— 管理员能够编辑博客和文章中的文本和图像,以及添加新页面。
  该项目花费了大约六个月的时间来完成,另外花了两个月的调试时间。如果我需要从头开始构建所有,或者尝试重新设计现有的框架以满足我们的需求,那将花费更长的时间,而且可能最终无法满足客户需求。
  
  功能和优点
  PHP Codeigniter还有很多吸引开发者的功能,包括错误处理和代码格式化,这些功能在各种编码情景下都非常有用。它支持模板,可用于向现有网站添加功能或生成新网站。有许多基于 web 系统商业需要的功能,包括使用自定义标签。即使没有编程经验的普通开发人员也可以使用大多数工具。
  Codeigniter 的主要功能是:
  ◈XML 核心服务,◈HTTP/FTP 核心服务◈AppData 和 PHP 沙箱功能◈XSLT 和 HTML 模板◈加密的信息传输◈PCM Codeigniter 服务器监控◈应用集成◈文件传输协议(FTP)◈服务台支持◈Apache POI(用于托管网站的内容管理基础架构)
  
  兼容性
  Codeigniter 与许多领先的软件程序兼容,例如 PHP、MySQL、MariaDB、phpMyAdmin、Apache、OpenBSD、XSLT、SQLite等。许多公司更喜欢使用 Codeigniter 产品来满足网站要求,因为它们易于使用和集成。如果你不想创建自己的网站,你可以找到许多提供自定义 Web 开发服务的开发人员和设计机构。
  
  安全
  Codeigniter 还通过 SSL 加密提供数据安全性。加密可以保护数据免受入侵者和防火墙外部威胁的侵害。数据存储功能还允许对公司网站进行安全审核。
  
  其它功能
  一家优秀的 PHP Web 开发公司会使用几种高级技术和第三方技术,例如 XML 和 PHP。它为企业提供了一个完整的平台,可以开发出具有看起来专业的、好用的商业网站。Codeigniter 使得第三方技术的使用变得容易,并可以与常见的 Web 开发软件一起使用。这使得 Web 公司可以轻松地使用所选模块创建网站。大多数 PHP 开发者也为个人提供支持和培训服务。
  
  使用 PHP 框架 Codeigniter
  Codeigniter 给企业提供了完整的 PHP 开发包,它将提供强大的功能、灵活性和性能完美结合在一起。到目前为止,我很满意我们的网站,并不断地升级和添加新的功能。并不断升级和增加新的功能。我期待着发现我们的网站还能用 Codeigniter 做些什么。你也是这样么?
  via:
  作者:Wee Ben Sen选题:lujun9972译者:geekpi校对:wxy
  本文由LCTT原创编译,Linux中国荣誉推出
  

cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶

网站优化优采云 发表了文章 • 0 个评论 • 91 次浏览 • 2022-05-30 10:00 • 来自相关话题

  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶
  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶2.常用主题介绍和参数详解3.特色功能介绍和拓展介绍4.使用方法整理和总结5.历史功能清单根据工具类型,
  cms,比如7k7k、uiwebshop、wp、pageadmin、wordpress、discuz等等这些都是不错的设计模板、程序主题、插件程序和模板。有兴趣的可以加下微信好友。
  这种网站可以实现做php版的啊,我这里做的一个npm版本的网站,当然也能用前端语言写,网站框架我没设计过,我用的db5和wordpress,网站来源于小程序搜索推荐,
  那些好用的开源php后台主题及使用方法
  cms后台都有后台模板,只要是php就能一键换框架,所以原则上没有比较好用的版本,同样都是php的话,用谁的,用前端开发的那个都能实现你要的功能。
  php后台程序+cms美化框架程序+扩展php后台程序只是最基本的内容,多数后台需要处理逻辑、还有反应时间,但这些功能都可以用cms框架开发。要注意框架的选择!如果没有考虑用户体验,用自己原来写的没有问题,但用框架开发的话,你可以为他重写整个模板,速度快,但以后有bug能修复吗?如果你们公司以后需要扩展功能,你可以为扩展重写整个框架,但后期有bug你能修复吗?以后扩展需要update那些数据库模块,你们知道维护吗?有时用户申请模版都返回不了,要重新重写mvc模式,没有这个功能就进不去,模版不稳定时,网站浏览器看起来是不稳定,查看不到。
  而模版稳定就直接满足要求。当然框架看上去好看,还有很多具体应用可以用,比如,你前端写一个类似的框架,一般带时下的主流框架,像uiwebshop这些,你可以带标签、带颜色等等,但你后台写的太好了,用户会觉得你有多套后台,使用了各种的插件程序,很烦,更可能用户使用不了。找个框架吧,方便事物也多,国内多数的框架大同小异,看哪个功能强大简单易用快速,你就用哪个。
  cms的应用,你需要有学习整个框架语言,图形化做外观界面,操作也有快捷键,能访问数据库等。视觉好看的框架是好,多一个功能也可以省事,设计好的页面功能丰富全,感觉不到有换了个版本,功能比较强大。然后每个网站不同,都有一些功能需要处理,对接不一样的外网,模板上也可以和外网访问联动,具体要看具体情况。你的功能要注意的。 查看全部

  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶
  cms网站后台内容管理系统模板化程度:高功能模板的功能强大到让你惊讶2.常用主题介绍和参数详解3.特色功能介绍和拓展介绍4.使用方法整理和总结5.历史功能清单根据工具类型,
  cms,比如7k7k、uiwebshop、wp、pageadmin、wordpress、discuz等等这些都是不错的设计模板、程序主题、插件程序和模板。有兴趣的可以加下微信好友。
  这种网站可以实现做php版的啊,我这里做的一个npm版本的网站,当然也能用前端语言写,网站框架我没设计过,我用的db5和wordpress,网站来源于小程序搜索推荐,
  那些好用的开源php后台主题及使用方法
  cms后台都有后台模板,只要是php就能一键换框架,所以原则上没有比较好用的版本,同样都是php的话,用谁的,用前端开发的那个都能实现你要的功能。
  php后台程序+cms美化框架程序+扩展php后台程序只是最基本的内容,多数后台需要处理逻辑、还有反应时间,但这些功能都可以用cms框架开发。要注意框架的选择!如果没有考虑用户体验,用自己原来写的没有问题,但用框架开发的话,你可以为他重写整个模板,速度快,但以后有bug能修复吗?如果你们公司以后需要扩展功能,你可以为扩展重写整个框架,但后期有bug你能修复吗?以后扩展需要update那些数据库模块,你们知道维护吗?有时用户申请模版都返回不了,要重新重写mvc模式,没有这个功能就进不去,模版不稳定时,网站浏览器看起来是不稳定,查看不到。
  而模版稳定就直接满足要求。当然框架看上去好看,还有很多具体应用可以用,比如,你前端写一个类似的框架,一般带时下的主流框架,像uiwebshop这些,你可以带标签、带颜色等等,但你后台写的太好了,用户会觉得你有多套后台,使用了各种的插件程序,很烦,更可能用户使用不了。找个框架吧,方便事物也多,国内多数的框架大同小异,看哪个功能强大简单易用快速,你就用哪个。
  cms的应用,你需要有学习整个框架语言,图形化做外观界面,操作也有快捷键,能访问数据库等。视觉好看的框架是好,多一个功能也可以省事,设计好的页面功能丰富全,感觉不到有换了个版本,功能比较强大。然后每个网站不同,都有一些功能需要处理,对接不一样的外网,模板上也可以和外网访问联动,具体要看具体情况。你的功能要注意的。

Repractise架构篇一: CMS的重构与演进

网站优化优采云 发表了文章 • 0 个评论 • 97 次浏览 • 2022-05-26 00:12 • 来自相关话题

  Repractise架构篇一: CMS的重构与演进
  架构师(JiaGouX)我们都是架构师!
  
  重构系统是一项非常具有挑战性的事情。通常来说,在我们的系统是第二个系统的时候才需要重构,即这个系统本身已经很臃肿。我们花费了太量的时间在代码间的逻辑,开发新的功能变得越来越慢。这不仅仅可能只是因为我们之前的架构没有设计好,而且在我们开发的过程中没有保持着原先设计时的一些原则。如果是这样的情况,那么这就是一个复杂的过程。
  还有一种情况是我们发现了一种更符合我们当前业务的框架。
  动态CMSCMS简介
  CMS是Content Management System的缩写,意为"内容管理系统".它可以做很多的事情,但是总的来说就是Page和Blog——即我们要创建一些页面可以用于写一些About US、Contact Me,以及持续更新的博客或者新闻,以及其他子系统——通常更新不活跃。通过对这些博客或者新闻进行分类,我们就可以有不同的信息内容,如下图:
  
  CMS是政府和企业都需要的系统,他们有很多的信息需要公开,并且需要对其组织进行宣传。在我有限的CMS交付经验里(大学时期),一般第一次交付CMS的时候,已经创建了大部分页面。有时候这些页面可能直接存储在数据库中,后来发现这不是一个好的方案,于是很多页面变成了静态页面。随后,在CMS的生命周期里就是更新内容。
  因而,CMS中起其主导的东西还是Content,即内容。而内容是一些持续可变的东西。这也就是为什么WordPress这么流行于CMS界,它是一个博客系统,但是多数时候我们只需要更新内容。除此不得不提及的一个CMS框架是Drupal,两者一对比会发现Drupal比较强大。通常来说,强大的一个负作用就是——复杂。
  WordPress和Drupal这一类的系统都属于发布系统,而其后台可以称为编辑系统。
  一般来说CMS有下面的特点:
  CMS一直就是这样一个紧耦合的系统。
  CMS架构与Django
  说起来,我一直是一个CMS党。主要原因还在于我可以随心所欲地去修改网站的内容,修改网站的架构。好的CMS总的来说都有其架构图,下图似乎是Drupal的模块图
  
  一般来说,其底层都会有:
  我一直在使用一个名为Django的Python Web框架,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。它是一个MTV框架——与多数的框架并没有太大的区别。
  层次职责
  模型(Model),即数据存取层
  处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  模板(Template),即表现层
  处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  视图(View),即业务逻辑层
  存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。
  从框架本身来上看它和别的系统没有太大的区别。
  
  但是如果我们已经有多外模块(即Django中app的概念),那么系统的架构就有所不同了。
  
  这就是为何我喜欢用这个CMS的原因了,我的每个子系统都以APP的形式提供服务——博客是一个app,sitemap是一个app,api是一个app。系统直接解耦为类似于混合服务的架构,即不像微服务一样多语言化,又不会有宏应用的紧耦合问题。
  编辑-发布分离
  我们的编辑和发布系统在某种意义上紧耦合在一起了,当用户访问量特别大的时候,这样会让我们的应用变得特定慢。有时候编辑甚至发布不了新的东西,如下图引示:
  
  或者你认识出了上图是源自Martin Folwer的编辑-发布分离
  编辑-发布分离是几年前解耦复杂系统游来开来带来的一个成果。今天这个似乎已经很常见了,编辑的时候是在后台进行的,等到发布的时候已经变成了一个静态的HTML。
  已经有足够多的CMS支持这样的特性,运行起来似乎特别不错,当然这样的系统也会有缓存的问题。有了APP这后,这个趋势就更加明显了——人们需要提供一个API。到底是在现有的系统里提供一个新的API,还是创建一个新的API。
  这时候,我更愿意选择后者——毕竟紧耦合一个系统总会在后期带来足够多的麻烦。而且基于数据库构建一个只读的RESTful API并不是一个复杂的过程,而且也危险。这时候的瓶颈就是数据库,但是似乎数据库都是多数系统的瓶颈。人们想出了各种各样的技术来解决这个瓶颈。
  于是之前我试着用Node.js + RESTify将我的博客重构成了一个SPA,当然这个时候CMS还在运行着。出于SEO的原因我并没有在最后采用这个方案,因为我网站的主要流量来源是Google和是百度。但是我在另外的网站里混合了SPA与MPA,其中的性能与应用是相当的,除了第一次加载页面的时候会带来一些延时。
  除了Node.js + RESTify,也试了试Python + Falcon(一个高性能的RESTful框架)。这个API理论上也应该可以给APP直接使用,并且可以直接拿来生成静态页面。
  编辑-发布-开发分离:静态站点生成
  如React一样解决DOM性能的问题就是跳过DOM这个坑,要跳过动态网站的性能问题就是让网站变成静态。
  越来越多的开发人员开始在使用Github Pages作为他们的博客,这是一个很有意思的转变。主要的原因是这是免费的,并且基本上可以保证24x7小时是可用的——当且仅当Github发现故障的时候才会不可访问。
  在这一类静态站点生成器(Github)里面,比较流行的有下面的内容(数据来源: ):
  Jekyll / OctoPress。Jekyll和OctoPress是最流行的静态博客系统。
  Hexo。Hexo是NodeJS编写的静态博客系统,其生成速度快,主题数量相对也比较丰富。是OctoPress的优秀替代者。
  Sculpin。Sculpin是PHP的静态站点系统。Hexo和Octopress专注于博客,而有时候我们的需求不仅仅是博客,而是有类似CMS的页面生成需求。Sculpin是一个泛用途的静态站点生成系统,在支持博客常见的分页、分类tag等同时,也能较好地支持非博客的一般页面生成。
  Hugo。Hugo是GO语言编写的静态站点系统。其生成速度快,且在较好支持博客和非博客内容的同时提供了比较完备的主题系统。无论是自己写主题还是套用别人的主题都比较顺手。
  通常这一类的工具里会有下面的内容:
  模板
  支持Markdown
  元数据
  如Hexo这样的框架甚至提供了一键部署的功能。
  在我们写了相关的代码之后,随后要做的就是生成HTML。对于个人博客来说,这是一个非常不错的系统,但是对于一些企业级的系统来说,我们的要求就更高了。如下图是Carrot采用的架构:
  
  这与我们在项目上的系统架构目前相似。作为一个博主,通常来说我们修改博客的主题的频率会比较低, 可能是半年一次。如果你经常修改博客的主题,你博客上的文章一定是相当的少。
  上图中的编辑者通过一个名为Contentful CMS来创建他们的内容,接着生成RESTful API。而类似的事情,我们也可以用Wordpress + RESTful 插件来完成。如果做得好,那么我想这个API也可以直接给APP使用。
  上图中的开发者需要不断地将修改的主题或者类似的东西PUSH到版本管理系统上,接着会有webhook监测到他们的变化,然后编译出新的静态页面。
  最后通过Netlify,他们编译到了一起,然后部署到生产环境。除了Netlify,你也可以编写生成脚本,然后用Bamboo、Go这类的CI工具进行编译。
  通常来说,生产环境可以使用CDN,如CloudFront服务。与动态网站相比,静态网站很容易直接部署到CDN,并可以直接从离用户近的本地缓存提供服务。除此,直接使用AWS S3的静态网站托管也是一个非常不错的选择。
  基于Github的编辑-发布-开发分离
  尽管我们已经在项目上实施了基于Github的部分内容管理已经有些日子里,但是由于找不到一些相关的资料,便不好透露相关的细节。直到我看到了《An Incremental Approach to Content Management Using Git 1》,我才意识到这似乎已经是一个成熟的技术了。看样子这项技术首先已经应用到了ThoughtWorks的官网上了。
  文中提到了使用这种架构的几个点:
  快速地开始项目,而不是学习或者配置框架。
  需要使用我们信奉的原则,如TDD。而这是大部分CMS所不支持的。
  基于服务的架构。
  灵活的语言和工具
  我们是开发人员。
  So,so,这些开发人员做了些什么:
  内容存储为静态文件
  不是所有的内容都是平等的
  引入内容服务
  使用Github。所有的content会提交到一个repo里,同时在我们push内容的时候,可以实时更新这些内容。
  允许内容通过内容服务更新
  使用Github API
  于是,有了一个名为Hacienda的框架用于管理内容,并存储为JSON。这意味着什么?
  
  因为使用了Git,我们可以了解到一个文件内容的历史版本,相比于WordPress来说更直观,而且更容易 上手。
  开发人员修改完他们的代码后,就可以直接提交,不会影响到Editor使用网站。Editor通过一个编辑器添加内容,在保存后,内容以JSON的形式出现直接提交代码到Github上相应的代码库中。CI或者Builder监测到他们的办法,就会生成新的静态页面。在这时候,我们可以选择有一个预览的平台,并且可以一键部署。那么,事情似乎就完成得差不多了。
  如果我们有APP,那么我们就可以使用Content Servies来做这些事情。甚至可以直接拿其搭建一个SPA。
  如果我们需要全文搜索功能,也变得很简单。我们已经不需要直接和数据库交互,我们可以直接读取JSON并且构建索引。这时候需要一个简单的Web服务,而且这个服务还是只读的。
  在需要的时候,如手机APP,我们可以通过Content Servies来创建博客。
  Repractise
  思考完这些后,我想到了一个符合学习的场景。
  
  我们构建的核心都可以基于Travis CI来完成,唯一存在风险的环节是我们似乎需要暴露我们的Key。
  其他
  参考文章:
  静态网站生成器将会成为下一个大热门
  EditingPublishingSeparation
  An Incremental Approach to Content Management Using Git 1
  Part 2: Implementing Content Management and Publication Using Git 查看全部

  Repractise架构篇一: CMS的重构与演进
  架构师(JiaGouX)我们都是架构师!
  
  重构系统是一项非常具有挑战性的事情。通常来说,在我们的系统是第二个系统的时候才需要重构,即这个系统本身已经很臃肿。我们花费了太量的时间在代码间的逻辑,开发新的功能变得越来越慢。这不仅仅可能只是因为我们之前的架构没有设计好,而且在我们开发的过程中没有保持着原先设计时的一些原则。如果是这样的情况,那么这就是一个复杂的过程。
  还有一种情况是我们发现了一种更符合我们当前业务的框架。
  动态CMSCMS简介
  CMS是Content Management System的缩写,意为"内容管理系统".它可以做很多的事情,但是总的来说就是Page和Blog——即我们要创建一些页面可以用于写一些About US、Contact Me,以及持续更新的博客或者新闻,以及其他子系统——通常更新不活跃。通过对这些博客或者新闻进行分类,我们就可以有不同的信息内容,如下图:
  
  CMS是政府和企业都需要的系统,他们有很多的信息需要公开,并且需要对其组织进行宣传。在我有限的CMS交付经验里(大学时期),一般第一次交付CMS的时候,已经创建了大部分页面。有时候这些页面可能直接存储在数据库中,后来发现这不是一个好的方案,于是很多页面变成了静态页面。随后,在CMS的生命周期里就是更新内容。
  因而,CMS中起其主导的东西还是Content,即内容。而内容是一些持续可变的东西。这也就是为什么WordPress这么流行于CMS界,它是一个博客系统,但是多数时候我们只需要更新内容。除此不得不提及的一个CMS框架是Drupal,两者一对比会发现Drupal比较强大。通常来说,强大的一个负作用就是——复杂。
  WordPress和Drupal这一类的系统都属于发布系统,而其后台可以称为编辑系统。
  一般来说CMS有下面的特点:
  CMS一直就是这样一个紧耦合的系统。
  CMS架构与Django
  说起来,我一直是一个CMS党。主要原因还在于我可以随心所欲地去修改网站的内容,修改网站的架构。好的CMS总的来说都有其架构图,下图似乎是Drupal的模块图
  
  一般来说,其底层都会有:
  我一直在使用一个名为Django的Python Web框架,它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。它是一个MTV框架——与多数的框架并没有太大的区别。
  层次职责
  模型(Model),即数据存取层
  处理与数据相关的所有事务:如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  模板(Template),即表现层
  处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  视图(View),即业务逻辑层
  存取模型及调取恰当模板的相关逻辑。模型与模板之间的桥梁。
  从框架本身来上看它和别的系统没有太大的区别。
  
  但是如果我们已经有多外模块(即Django中app的概念),那么系统的架构就有所不同了。
  
  这就是为何我喜欢用这个CMS的原因了,我的每个子系统都以APP的形式提供服务——博客是一个app,sitemap是一个app,api是一个app。系统直接解耦为类似于混合服务的架构,即不像微服务一样多语言化,又不会有宏应用的紧耦合问题。
  编辑-发布分离
  我们的编辑和发布系统在某种意义上紧耦合在一起了,当用户访问量特别大的时候,这样会让我们的应用变得特定慢。有时候编辑甚至发布不了新的东西,如下图引示:
  
  或者你认识出了上图是源自Martin Folwer的编辑-发布分离
  编辑-发布分离是几年前解耦复杂系统游来开来带来的一个成果。今天这个似乎已经很常见了,编辑的时候是在后台进行的,等到发布的时候已经变成了一个静态的HTML。
  已经有足够多的CMS支持这样的特性,运行起来似乎特别不错,当然这样的系统也会有缓存的问题。有了APP这后,这个趋势就更加明显了——人们需要提供一个API。到底是在现有的系统里提供一个新的API,还是创建一个新的API。
  这时候,我更愿意选择后者——毕竟紧耦合一个系统总会在后期带来足够多的麻烦。而且基于数据库构建一个只读的RESTful API并不是一个复杂的过程,而且也危险。这时候的瓶颈就是数据库,但是似乎数据库都是多数系统的瓶颈。人们想出了各种各样的技术来解决这个瓶颈。
  于是之前我试着用Node.js + RESTify将我的博客重构成了一个SPA,当然这个时候CMS还在运行着。出于SEO的原因我并没有在最后采用这个方案,因为我网站的主要流量来源是Google和是百度。但是我在另外的网站里混合了SPA与MPA,其中的性能与应用是相当的,除了第一次加载页面的时候会带来一些延时。
  除了Node.js + RESTify,也试了试Python + Falcon(一个高性能的RESTful框架)。这个API理论上也应该可以给APP直接使用,并且可以直接拿来生成静态页面。
  编辑-发布-开发分离:静态站点生成
  如React一样解决DOM性能的问题就是跳过DOM这个坑,要跳过动态网站的性能问题就是让网站变成静态。
  越来越多的开发人员开始在使用Github Pages作为他们的博客,这是一个很有意思的转变。主要的原因是这是免费的,并且基本上可以保证24x7小时是可用的——当且仅当Github发现故障的时候才会不可访问。
  在这一类静态站点生成器(Github)里面,比较流行的有下面的内容(数据来源: ):
  Jekyll / OctoPress。Jekyll和OctoPress是最流行的静态博客系统。
  Hexo。Hexo是NodeJS编写的静态博客系统,其生成速度快,主题数量相对也比较丰富。是OctoPress的优秀替代者。
  Sculpin。Sculpin是PHP的静态站点系统。Hexo和Octopress专注于博客,而有时候我们的需求不仅仅是博客,而是有类似CMS的页面生成需求。Sculpin是一个泛用途的静态站点生成系统,在支持博客常见的分页、分类tag等同时,也能较好地支持非博客的一般页面生成。
  Hugo。Hugo是GO语言编写的静态站点系统。其生成速度快,且在较好支持博客和非博客内容的同时提供了比较完备的主题系统。无论是自己写主题还是套用别人的主题都比较顺手。
  通常这一类的工具里会有下面的内容:
  模板
  支持Markdown
  元数据
  如Hexo这样的框架甚至提供了一键部署的功能。
  在我们写了相关的代码之后,随后要做的就是生成HTML。对于个人博客来说,这是一个非常不错的系统,但是对于一些企业级的系统来说,我们的要求就更高了。如下图是Carrot采用的架构:
  
  这与我们在项目上的系统架构目前相似。作为一个博主,通常来说我们修改博客的主题的频率会比较低, 可能是半年一次。如果你经常修改博客的主题,你博客上的文章一定是相当的少。
  上图中的编辑者通过一个名为Contentful CMS来创建他们的内容,接着生成RESTful API。而类似的事情,我们也可以用Wordpress + RESTful 插件来完成。如果做得好,那么我想这个API也可以直接给APP使用。
  上图中的开发者需要不断地将修改的主题或者类似的东西PUSH到版本管理系统上,接着会有webhook监测到他们的变化,然后编译出新的静态页面。
  最后通过Netlify,他们编译到了一起,然后部署到生产环境。除了Netlify,你也可以编写生成脚本,然后用Bamboo、Go这类的CI工具进行编译。
  通常来说,生产环境可以使用CDN,如CloudFront服务。与动态网站相比,静态网站很容易直接部署到CDN,并可以直接从离用户近的本地缓存提供服务。除此,直接使用AWS S3的静态网站托管也是一个非常不错的选择。
  基于Github的编辑-发布-开发分离
  尽管我们已经在项目上实施了基于Github的部分内容管理已经有些日子里,但是由于找不到一些相关的资料,便不好透露相关的细节。直到我看到了《An Incremental Approach to Content Management Using Git 1》,我才意识到这似乎已经是一个成熟的技术了。看样子这项技术首先已经应用到了ThoughtWorks的官网上了。
  文中提到了使用这种架构的几个点:
  快速地开始项目,而不是学习或者配置框架。
  需要使用我们信奉的原则,如TDD。而这是大部分CMS所不支持的。
  基于服务的架构。
  灵活的语言和工具
  我们是开发人员。
  So,so,这些开发人员做了些什么:
  内容存储为静态文件
  不是所有的内容都是平等的
  引入内容服务
  使用Github。所有的content会提交到一个repo里,同时在我们push内容的时候,可以实时更新这些内容。
  允许内容通过内容服务更新
  使用Github API
  于是,有了一个名为Hacienda的框架用于管理内容,并存储为JSON。这意味着什么?
  
  因为使用了Git,我们可以了解到一个文件内容的历史版本,相比于WordPress来说更直观,而且更容易 上手。
  开发人员修改完他们的代码后,就可以直接提交,不会影响到Editor使用网站。Editor通过一个编辑器添加内容,在保存后,内容以JSON的形式出现直接提交代码到Github上相应的代码库中。CI或者Builder监测到他们的办法,就会生成新的静态页面。在这时候,我们可以选择有一个预览的平台,并且可以一键部署。那么,事情似乎就完成得差不多了。
  如果我们有APP,那么我们就可以使用Content Servies来做这些事情。甚至可以直接拿其搭建一个SPA。
  如果我们需要全文搜索功能,也变得很简单。我们已经不需要直接和数据库交互,我们可以直接读取JSON并且构建索引。这时候需要一个简单的Web服务,而且这个服务还是只读的。
  在需要的时候,如手机APP,我们可以通过Content Servies来创建博客。
  Repractise
  思考完这些后,我想到了一个符合学习的场景。
  
  我们构建的核心都可以基于Travis CI来完成,唯一存在风险的环节是我们似乎需要暴露我们的Key。
  其他
  参考文章:
  静态网站生成器将会成为下一个大热门
  EditingPublishingSeparation
  An Incremental Approach to Content Management Using Git 1
  Part 2: Implementing Content Management and Publication Using Git

CloudBase CMS + Next.js:轻松构建一个内容丰富的站点

网站优化优采云 发表了文章 • 0 个评论 • 170 次浏览 • 2022-05-24 04:14 • 来自相关话题

  CloudBase CMS + Next.js:轻松构建一个内容丰富的站点
  项目背景试想一下,如果你现在要为你自己或者你所在的组织创建一个强内容的站点,同时要求好的 SEO(搜素引擎优化),比如博客,你会怎么做呢?
  由 vite 或者 create-react-app 等脚手架构建的普通 SPA 应用是不行的,因为这样数据都是通过 AJAX 返回的。你暂时不了解这些概念也没关系,你只需要知道,这种方式下,搜索引擎是无法很好地了解你的网站是干什么的,所以就算大众在搜索引擎搜索你的站点的相关内容,搜索引擎也很难把你的站点排在搜索结果前列。那么为每个页面都编写一个静态的 html 页面呢?比如,为每篇文章都编写一个 html 文件,然后放在服务器上,这样只要客户端请求某篇文章,服务器就把对应的文章页面直接返回。这样也不好,太麻烦了,如果每次更改内容,都要用硬编码的方式去应对,那就把事情弄得太复杂了。如果有一种后台系统,能让管理员通过后台系统的简单操作,就能修改网站呈现的内容就好了。
  
  SPA 应用
  
  纯粹静态网站开发本文就将带领你采用一种新颖的、便捷的开发方式——通过结合 CloudBase CMS 和 Next.js,去构建内容管理方便,利于 SEO 且响应快速的站点。CMS 是云开发 CloudBase 推出的一款无头(headless)内容管理系统,提供给开发者方便地管理内容资源的能力。所谓无头,意思就是内容管理系统只负责管理你的内容,比如文章内容和作者列表。这些内容可以在客户端或者服务端通过 SDK 或者 API 的方式去取得。而如何去展示这些内容,则由开发者自行全权掌控。Next.js 是一款生产级的 React 框架,它提供了静态生成的功能。静态生成的意思是,在构建的过程中,Next.js 就会自动执行数据拉取的逻辑,并把数据和 UI 渲染为一个个的静态 HTML 页面,这意味着,我们的站点将响应迅速,而且利于 SEO。
  
  本文将通过带领你构建一个个人博客,以展示如何结合这两者,并最终在腾讯云云开发上部署站点。Demo在线预览
  
  开启环境和项目1. 开通 CloudBase CMS首先,你要在腾讯云控制台开通你的第一个云开发环境。云开发环境是云开发中的一个概念,每个云环境都集成了应用开发需要的基础能力,比如云数据库、云函数,开发者可以方便地组合、使用它们,为应用开发赋能。TCB-CMS 也是建立在云环境之上的。创建环境时,你可以直接选择空模板并勾选免费资源选项即可,最后将环境命名为 my-blog。
  
  可以看到,环境已经在创建中了。环境创建完毕后,进入扩展应用模块,可以看到“CMS内容管理系统”,可以在这里安装它。设置都按照默认就可以了,唯一要注意的是,务必记住自己设置的管理员账号和密码。等安装完毕后,可以在已安装应用一栏中进入应用。点击访问地址后,我们可以直接访问应用。进入应用并输入管理员账号和密码,然后可以看到以下页面:
  
  现在,系统中还没有任何项目,点击创建一个名为 MyBlog 的新项目,创建完毕后进入项目,可以看到内容模型和内容集合,拿数据库作类比,这两者就是数据库表和数据库表内容的关系,这两者就是我们要设置和管理的内容。已经有准备好的数据可以直接导入,分别就在项目源码仓库中的 ./schema 和 ./data 文件夹中。点击导入按钮,然后选择导入文件即可。好了,现在 CMS 已经成功开通了,我们也往其中加入了内容。接下来,就可以着手 Next.js 应用的编写了。
  2. 启动 Next.js 项目Next.js 是构建于 React 之上的生产级前端框架。相比于原本的 React,Next.js 提供了静态生成、服务端渲染等特性,同时自带前端路由,我们这次就主要用到 Next.js 的静态生成功能。使用 Next.js 编写前端应用,和使用 create-react-app 脚手架编写 SPA 应用非常类似,而且更加便捷、开箱即用。直接在命令行执行以下命令可以创建 Next.js 的样板项目并启动它:
  npx create-next-app<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />npm run dev<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  访问 localhost:3000 可以看到以下效果:
  
  接下来,我们就将基于这个样板项目开发网站。首页这里,我们将在首页放置文章列表。首先,打开项目下的 ./pages/index.js,发现页面导出了一个函数式的 React 组件。在 Next.js 中,pages 目录下,除了 api 文件夹下的内容和 _app.js,其他每个 js 文件导出的 React 组件都对应着一个或者一种页面,并且由 Next.js 直接生成对应的路由,index.js 导出的函数式组件就直接对应着我们进入网站后的第一个页面,而其他 js 文件于 ./pages 的相对地址就是 Next.js 为其自动生成的路由。Next.js 在应用构建期,就会对每个页面执行数据拉取的逻辑,并根据 React 组件构建的 UI,渲染出最后的 HTML 页面,接下来,我们要做的就是,构建主页的 UI,以及为主页编写拉取数据的逻辑。UI 编写接下来对主页的 UI 进行修改:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Home({ posts }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 云开发小站<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Welcome to 云开发 CloudBase!<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {posts.map(post => (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {post.title} &rarr;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <p>{post.author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> ))}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}</p>
  可以看到,修改后的 Home 组件,接受了一个 posts 为参数,这个 post 就是文章列表数据,我们将它在组件中渲染出来。那么 post 从哪里来呢?在同一个 js 文件下,需要再导出一个 getStaticProps 函数。
  export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}
  这个函数返回的对象的 props 属性,就是导出的函数式组件用到的参数。所以,只需要在 getStaticProps 函数中得到数据并返回即可。拉取数据先安装拉取数据要用到的 SDK:
  npm install --save @cloudbase/node-sdk
  然后,我们再创建 env.js 文件,在其中填入云环境相关信息:
  export const tcbConfig = {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    env: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretId: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretKey: ''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中环境ID(env)可以直接在环境主页中看到,API 密钥(secretId,secretKey)则可以在访问管理中获取。最后,我们创建 ./lib/api.js,然后填入以下内容,将数据拉取的逻辑全部集中在这个文件中。
  import tcb from '@cloudbase/node-sdk';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { tcbConfig } from '../env';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const { Author, Article } = (() => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const db = tcb.init(tcbConfig).database();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Author: db.collection('author'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Article: db.collection('article'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />})();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getHomePosts = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const posts = (await Article<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({})<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .orderBy('_updateTime', 'desc')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .limit(10)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    for (const post of posts) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        const { name } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        posts<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  在 api.js 中,根据环境信息,对 SDK 进行了初始化,并创建了用于查询文章和作者的实例 Author 和 Ariticle。在 getHomePosts 函数中,我们获取了展示用的文章。具体的逻辑如果不懂也暂时不必深究,现在只需要知道:通过执行 getHomePosts 我们能从云环境的 CMS 系统中拉取文章列表。接着,再来修改 ./pages/index.js 文件:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getHomePosts } from '../lib/api'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: await getHomePosts()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,再访问 localhost:3000,可以看到如下效果:
  
  这标志着:我们成功从 CMS 中获取数据并能够渲染出静态页面来返回给客户端啦!文章页面接下来,就要着手编写文章页面了,基本流程差不多,但值得注意的是,文章页面和主页不同,只有一个主页,但是文章页面可能有无数个,而Next.js 提供了能力,能让我们只编写一个 js 文件,并加以细微的改动,就能渲染出无数的文章页面 。拉取用以渲染页面的文章内容先准备好需要的样式。首先创建 ./styles/Post.module.css 文件,具体样式内容可以参考:接着,创建 ./pages/post/[id].js 文件,这个文件对应的,就是路由形如 /post/{id} 的所有页面,而 id 的作用就是匹配文章的 _id。这样通过访问 URL:/post/{id1}.js,就能访问到文章id等于 id1 的文章对应页面。我们先往 [id].js 文件中填入以下的内容:
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Post({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> title,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> image,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> author,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> avator,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> contentHtml<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <img className={styles.image} src={image}></img><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 返回<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到,相比 index.js,[id].js 多出了一个 getStaticProps 函数,getStaticProps 也多了一个 parms 参数。getStaticProps 函数暂时不用管,而 param.id 就是在路由中匹配到的 id,可以借助它,执行获取对应文章内容的逻辑。在 api.js 中,添加以下内容:
  // 对于 image 类型的字段,直接取得的 id 需要转换为可用的 URL<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const dealWithUrl = url => 'https://' + url<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace(`cloud://${tcbConfig.env}.`, '')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace('/cloudbase-cms', '.tcb.qcloud.la/cloudbase-cms');<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getPost = async (id) => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const post = (await Article.where({ _id: id }).get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const { name, avator } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.avator = dealWithUrl(avator);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.image = dealWithUrl(post.image);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return post;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后安装 remark 以及 remark-html 两个库,我们将用它们把 markdown 转化为 html,然后修改 [id].js 文件中的 getStaticProps 为
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getPost } from '../../lib/api';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import remark from 'remark'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import html from 'remark-html'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const post = await getPost(params.id);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const processedContent = await remark()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .use(html)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .process(post.content)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> post.contentHtml = processedContent.toString()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: post<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  拉取所有的文章id以渲染所有文章页面只到这一步还不够,我们需要知道所有的路由可能匹配到的 id 值,Next.js 才能渲染出全部的文章页面。[id].js 多出的 getStaticPaths 函数正是用来返回 id 所有可能的匹配值的。这就是我们只需要编写一次拉取文章数据逻辑,编写一次文章页面 UI,就能让 Next.js 生成出无数文章的静态页面的奥秘。因为,可以让 Next.js 知道所有的文章 id,然后 Next.js 就能对每个文章页面执行一次生成了。修改往 api.js 中添加获取所有文章 id 的函数:
  export const getAllPostId = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    let posts = (await Article.where({}).get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return posts.map(value => ({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        params: { id: value._id }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后修改 getStaticPaths 函数:
  export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: await getAllPostId(),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,访问首页,随便进入一篇文章,就可以看到如下效果:
  
  到这里,我们就成功完成 Next.js 项目的构建啦!部署使用腾讯云云开发,你可以轻易地将应用部署到公共网络上。我们先修改 package.json 中依赖库的配置,因为云开发环境对于依赖版本有一定限制:
  "dependencies": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "@cloudbase/node-sdk": "^2.5.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "next": "9.5.4",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react-dom": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark": "^13.0.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark-html": "^13.0.1"<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,创建部署的配置文件 cloudbaserc.json,并填入以下内容:
  {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "envId": "{{env}}",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "version": "2.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "$schema": "https://framework-1258016615.t ... ot%3B,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functionRoot": "./functions",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functions": [],<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "region": "ap-shanghai",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "framework": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "name": "tcbcms-nextjs",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "plugins": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            "client": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "use": "@cloudbase/framework-plugin-next",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "inputs": {}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中的 env 换成你刚刚创建的云环境的 ID。修改完毕后,执行命令:
  cloudbase<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到部署流程启动,等待到部署完毕后,进入云环境的“我的应用”模块,会发现应用列表多了一个“tcbcms-nextjs”,点击访问键,就能访问刚刚创建的应用,而且是通过公网 IP,这说明我们的应用已经部署成功了。
  总结到此,我们的博客已经成功创建并部署了。以后如果博客中要添加新文章,或者要删改原有的文章,都只需要在 CMS 上进行内容的改动,然后在本地执行 Next.js 的构建和云开发部署即可。
  
  更多 Next.js 和云开发相关知识,可以查看官方文档:
  Next.js 官方文档:
  CloudBase CMS 官方文档:
  @cloudbase/node-sdk 官方文档:
  彩蛋:云开发是如何支撑应用开发的?你可能会好奇云环境的能力是如何支撑我们的系统的。再次进入腾讯云控制台,进入刚刚创建的云环境主页,进入HTTP访问服务、云数据库以及云函数模块,会发现多了许多东西。实际上,CMS 系统就是由这些东西支撑着的。我们每次访问 CMS 系统并操作,都会经由 HTTP访问服务,导向某个云函数,在云函数中执行后台逻辑,而系统中的数据,也都存储在云数据库中,这也是我们可以通过 @cloudbase/node-sdk 访问云数据库得到 CMS 中的数据的原因。而我们刚刚部署的 Next 应用,实际上也是运行在云函数上的。
  如果有兴趣在云开发中更进一步,欢迎前往云开发社区官网 阅读文档,加入,一起探索云开发的更多可能性。 查看全部

  CloudBase CMS + Next.js:轻松构建一个内容丰富的站点
  项目背景试想一下,如果你现在要为你自己或者你所在的组织创建一个强内容的站点,同时要求好的 SEO(搜素引擎优化),比如博客,你会怎么做呢?
  由 vite 或者 create-react-app 等脚手架构建的普通 SPA 应用是不行的,因为这样数据都是通过 AJAX 返回的。你暂时不了解这些概念也没关系,你只需要知道,这种方式下,搜索引擎是无法很好地了解你的网站是干什么的,所以就算大众在搜索引擎搜索你的站点的相关内容,搜索引擎也很难把你的站点排在搜索结果前列。那么为每个页面都编写一个静态的 html 页面呢?比如,为每篇文章都编写一个 html 文件,然后放在服务器上,这样只要客户端请求某篇文章,服务器就把对应的文章页面直接返回。这样也不好,太麻烦了,如果每次更改内容,都要用硬编码的方式去应对,那就把事情弄得太复杂了。如果有一种后台系统,能让管理员通过后台系统的简单操作,就能修改网站呈现的内容就好了。
  
  SPA 应用
  
  纯粹静态网站开发本文就将带领你采用一种新颖的、便捷的开发方式——通过结合 CloudBase CMS 和 Next.js,去构建内容管理方便,利于 SEO 且响应快速的站点。CMS 是云开发 CloudBase 推出的一款无头(headless)内容管理系统,提供给开发者方便地管理内容资源的能力。所谓无头,意思就是内容管理系统只负责管理你的内容,比如文章内容和作者列表。这些内容可以在客户端或者服务端通过 SDK 或者 API 的方式去取得。而如何去展示这些内容,则由开发者自行全权掌控。Next.js 是一款生产级的 React 框架,它提供了静态生成的功能。静态生成的意思是,在构建的过程中,Next.js 就会自动执行数据拉取的逻辑,并把数据和 UI 渲染为一个个的静态 HTML 页面,这意味着,我们的站点将响应迅速,而且利于 SEO。
  
  本文将通过带领你构建一个个人博客,以展示如何结合这两者,并最终在腾讯云云开发上部署站点。Demo在线预览
  
  开启环境和项目1. 开通 CloudBase CMS首先,你要在腾讯云控制台开通你的第一个云开发环境。云开发环境是云开发中的一个概念,每个云环境都集成了应用开发需要的基础能力,比如云数据库、云函数,开发者可以方便地组合、使用它们,为应用开发赋能。TCB-CMS 也是建立在云环境之上的。创建环境时,你可以直接选择空模板并勾选免费资源选项即可,最后将环境命名为 my-blog。
  
  可以看到,环境已经在创建中了。环境创建完毕后,进入扩展应用模块,可以看到“CMS内容管理系统”,可以在这里安装它。设置都按照默认就可以了,唯一要注意的是,务必记住自己设置的管理员账号和密码。等安装完毕后,可以在已安装应用一栏中进入应用。点击访问地址后,我们可以直接访问应用。进入应用并输入管理员账号和密码,然后可以看到以下页面:
  
  现在,系统中还没有任何项目,点击创建一个名为 MyBlog 的新项目,创建完毕后进入项目,可以看到内容模型和内容集合,拿数据库作类比,这两者就是数据库表和数据库表内容的关系,这两者就是我们要设置和管理的内容。已经有准备好的数据可以直接导入,分别就在项目源码仓库中的 ./schema 和 ./data 文件夹中。点击导入按钮,然后选择导入文件即可。好了,现在 CMS 已经成功开通了,我们也往其中加入了内容。接下来,就可以着手 Next.js 应用的编写了。
  2. 启动 Next.js 项目Next.js 是构建于 React 之上的生产级前端框架。相比于原本的 React,Next.js 提供了静态生成、服务端渲染等特性,同时自带前端路由,我们这次就主要用到 Next.js 的静态生成功能。使用 Next.js 编写前端应用,和使用 create-react-app 脚手架编写 SPA 应用非常类似,而且更加便捷、开箱即用。直接在命令行执行以下命令可以创建 Next.js 的样板项目并启动它:
  npx create-next-app<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />npm run dev<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  访问 localhost:3000 可以看到以下效果:
  
  接下来,我们就将基于这个样板项目开发网站。首页这里,我们将在首页放置文章列表。首先,打开项目下的 ./pages/index.js,发现页面导出了一个函数式的 React 组件。在 Next.js 中,pages 目录下,除了 api 文件夹下的内容和 _app.js,其他每个 js 文件导出的 React 组件都对应着一个或者一种页面,并且由 Next.js 直接生成对应的路由,index.js 导出的函数式组件就直接对应着我们进入网站后的第一个页面,而其他 js 文件于 ./pages 的相对地址就是 Next.js 为其自动生成的路由。Next.js 在应用构建期,就会对每个页面执行数据拉取的逻辑,并根据 React 组件构建的 UI,渲染出最后的 HTML 页面,接下来,我们要做的就是,构建主页的 UI,以及为主页编写拉取数据的逻辑。UI 编写接下来对主页的 UI 进行修改:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Home({ posts }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 云开发小站<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Welcome to 云开发 CloudBase!<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {posts.map(post => (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {post.title} &rarr;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <p>{post.author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> ))}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}</p>
  可以看到,修改后的 Home 组件,接受了一个 posts 为参数,这个 post 就是文章列表数据,我们将它在组件中渲染出来。那么 post 从哪里来呢?在同一个 js 文件下,需要再导出一个 getStaticProps 函数。
  export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}
  这个函数返回的对象的 props 属性,就是导出的函数式组件用到的参数。所以,只需要在 getStaticProps 函数中得到数据并返回即可。拉取数据先安装拉取数据要用到的 SDK:
  npm install --save @cloudbase/node-sdk
  然后,我们再创建 env.js 文件,在其中填入云环境相关信息:
  export const tcbConfig = {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    env: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretId: '',<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    secretKey: ''<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中环境ID(env)可以直接在环境主页中看到,API 密钥(secretId,secretKey)则可以在访问管理中获取。最后,我们创建 ./lib/api.js,然后填入以下内容,将数据拉取的逻辑全部集中在这个文件中。
  import tcb from '@cloudbase/node-sdk';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { tcbConfig } from '../env';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const { Author, Article } = (() => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const db = tcb.init(tcbConfig).database();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Author: db.collection('author'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        Article: db.collection('article'),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />})();<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getHomePosts = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const posts = (await Article<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({})<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .orderBy('_updateTime', 'desc')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .limit(10)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    for (const post of posts) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        const { name } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        posts<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  在 api.js 中,根据环境信息,对 SDK 进行了初始化,并创建了用于查询文章和作者的实例 Author 和 Ariticle。在 getHomePosts 函数中,我们获取了展示用的文章。具体的逻辑如果不懂也暂时不必深究,现在只需要知道:通过执行 getHomePosts 我们能从云环境的 CMS 系统中拉取文章列表。接着,再来修改 ./pages/index.js 文件:
  import Head from 'next/head'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../styles/Home.module.css'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getHomePosts } from '../lib/api'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: await getHomePosts()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,再访问 localhost:3000,可以看到如下效果:
  
  这标志着:我们成功从 CMS 中获取数据并能够渲染出静态页面来返回给客户端啦!文章页面接下来,就要着手编写文章页面了,基本流程差不多,但值得注意的是,文章页面和主页不同,只有一个主页,但是文章页面可能有无数个,而Next.js 提供了能力,能让我们只编写一个 js 文件,并加以细微的改动,就能渲染出无数的文章页面 。拉取用以渲染页面的文章内容先准备好需要的样式。首先创建 ./styles/Post.module.css 文件,具体样式内容可以参考:接着,创建 ./pages/post/[id].js 文件,这个文件对应的,就是路由形如 /post/{id} 的所有页面,而 id 的作用就是匹配文章的 _id。这样通过访问 URL:/post/{id1}.js,就能访问到文章id等于 id1 的文章对应页面。我们先往 [id].js 文件中填入以下的内容:
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export default function Post({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> title,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> image,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> author,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> avator,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> contentHtml<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return (<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <img className={styles.image} src={image}></img><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {title}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> {author}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> 返回<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> Powered by{' '}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> </a><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> <br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> )<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: undefined,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: undefined<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到,相比 index.js,[id].js 多出了一个 getStaticProps 函数,getStaticProps 也多了一个 parms 参数。getStaticProps 函数暂时不用管,而 param.id 就是在路由中匹配到的 id,可以借助它,执行获取对应文章内容的逻辑。在 api.js 中,添加以下内容:
  // 对于 image 类型的字段,直接取得的 id 需要转换为可用的 URL<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />const dealWithUrl = url => 'https://' + url<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace(`cloud://${tcbConfig.env}.`, '')<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    .replace('/cloudbase-cms', '.tcb.qcloud.la/cloudbase-cms');<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export const getPost = async (id) => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const post = (await Article.where({ _id: id }).get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    const { name, avator } = (await Author<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .where({ _id: post.author })<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        .get()).data[0];<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.author = name;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.avator = dealWithUrl(avator);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    post.image = dealWithUrl(post.image);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return post;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后安装 remark 以及 remark-html 两个库,我们将用它们把 markdown 转化为 html,然后修改 [id].js 文件中的 getStaticProps 为
  import Head from 'next/head';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import Link from 'next/link';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import styles from '../../styles/Post.module.css';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import { getPost } from '../../lib/api';<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import remark from 'remark'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />import html from 'remark-html'<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />...<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />export async function getStaticProps({ params }) {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const post = await getPost(params.id);<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> const processedContent = await remark()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .use(html)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> .process(post.content)<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> post.contentHtml = processedContent.toString()<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /><br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> props: post<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  拉取所有的文章id以渲染所有文章页面只到这一步还不够,我们需要知道所有的路由可能匹配到的 id 值,Next.js 才能渲染出全部的文章页面。[id].js 多出的 getStaticPaths 函数正是用来返回 id 所有可能的匹配值的。这就是我们只需要编写一次拉取文章数据逻辑,编写一次文章页面 UI,就能让 Next.js 生成出无数文章的静态页面的奥秘。因为,可以让 Next.js 知道所有的文章 id,然后 Next.js 就能对每个文章页面执行一次生成了。修改往 api.js 中添加获取所有文章 id 的函数:
  export const getAllPostId = async () => {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    let posts = (await Article.where({}).get()).data;<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    return posts.map(value => ({<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        params: { id: value._id }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }))<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />};<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后修改 getStaticPaths 函数:
  export async function getStaticPaths() {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> return {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> paths: await getAllPostId(),<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> fallback: false<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" /> };<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,访问首页,随便进入一篇文章,就可以看到如下效果:
  
  到这里,我们就成功完成 Next.js 项目的构建啦!部署使用腾讯云云开发,你可以轻易地将应用部署到公共网络上。我们先修改 package.json 中依赖库的配置,因为云开发环境对于依赖版本有一定限制:
  "dependencies": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "@cloudbase/node-sdk": "^2.5.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "next": "9.5.4",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "react-dom": "16.13.1",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark": "^13.0.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "remark-html": "^13.0.1"<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  然后,创建部署的配置文件 cloudbaserc.json,并填入以下内容:
  {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "envId": "{{env}}",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "version": "2.0",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "$schema": "https://framework-1258016615.t ... ot%3B,<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functionRoot": "./functions",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "functions": [],<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "region": "ap-shanghai",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    "framework": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "name": "tcbcms-nextjs",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        "plugins": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            "client": {<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "use": "@cloudbase/framework-plugin-next",<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />                "inputs": {}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />            }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />        }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />    }<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />}<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  其中的 env 换成你刚刚创建的云环境的 ID。修改完毕后,执行命令:
  cloudbase<br style="margin: 0px;padding: 0px;max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;" />
  可以看到部署流程启动,等待到部署完毕后,进入云环境的“我的应用”模块,会发现应用列表多了一个“tcbcms-nextjs”,点击访问键,就能访问刚刚创建的应用,而且是通过公网 IP,这说明我们的应用已经部署成功了。
  总结到此,我们的博客已经成功创建并部署了。以后如果博客中要添加新文章,或者要删改原有的文章,都只需要在 CMS 上进行内容的改动,然后在本地执行 Next.js 的构建和云开发部署即可。
  
  更多 Next.js 和云开发相关知识,可以查看官方文档:
  Next.js 官方文档:
  CloudBase CMS 官方文档:
  @cloudbase/node-sdk 官方文档:
  彩蛋:云开发是如何支撑应用开发的?你可能会好奇云环境的能力是如何支撑我们的系统的。再次进入腾讯云控制台,进入刚刚创建的云环境主页,进入HTTP访问服务、云数据库以及云函数模块,会发现多了许多东西。实际上,CMS 系统就是由这些东西支撑着的。我们每次访问 CMS 系统并操作,都会经由 HTTP访问服务,导向某个云函数,在云函数中执行后台逻辑,而系统中的数据,也都存储在云数据库中,这也是我们可以通过 @cloudbase/node-sdk 访问云数据库得到 CMS 中的数据的原因。而我们刚刚部署的 Next 应用,实际上也是运行在云函数上的。
  如果有兴趣在云开发中更进一步,欢迎前往云开发社区官网 阅读文档,加入,一起探索云开发的更多可能性。

一款神仙儿宝藏级微服务开源项目,吊到炸裂!

网站优化优采云 发表了文章 • 0 个评论 • 79 次浏览 • 2022-05-23 10:52 • 来自相关话题

  一款神仙儿宝藏级微服务开源项目,吊到炸裂!
  大家好,我是Java架构师
  今天,推荐一个宝藏级微服务开源项目。我第一次使用就有点上头,爱不释手,必须要推荐给大家。
  上次是谁要的宝藏级微服务开源项目啊,我帮你找到了。
  这是我目前见过最好的宝藏级微服务开源项目。功能完整,代码结构清晰。值得推荐。 项目介绍
  前几天有粉丝留言,正在学习微服务,想让我推荐一个微服务学习项目。这次我拿出了压箱底的收藏了,一个宝藏级微服务开源项目,炸裂!
  前言
  zheng项目不仅仅是一个开发架构,而是努力打造一套从前端模板-基础框架-分布式架构-开源项目-持续集成-自动化部署-系统监测-无缝升级的全方位J2EE企业级开发解决方案。扩展:
  项目介绍
  基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公共微服务服务模块:内容管理、支付中心、用户管理(包括第三方)、微信平台、存储系统、配置中心、日志分析、任务和通知等,支持服务治理、监控和追踪,努力为中小型企业打造全方位J2EE企业级开发解决方案。
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!赶快收藏吧...</p>
  组织结构
  zheng<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-common -- SSM框架公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-admin -- 后台管理模板<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ui -- 前台thymeleaf模板[端口:1000]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-config -- 配置中心[端口:1001]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-upms -- 用户权限管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-common -- upms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-client -- 集成upms依赖包,提供单点认证、授权、统一会话管理<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-upms-server -- 用户权限系统及SSO服务端[端口:1111]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-cms -- 内容管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-common -- cms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-search -- 搜索服务[端口:2221]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-admin -- 后台管理[端口:2222]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-job -- 消息队列、任务调度等[端口:2223]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-cms-web -- 网站前台[端口:2224]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-pay -- 支付系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-common -- pay系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-admin -- 后台管理[端口:3331]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-pay-web -- 演示示例[端口:3332]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ucenter -- 用户系统(包括第三方登录)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-common -- ucenter系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-web -- 网站前台[端口:4441]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-wechat -- 微信系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-wechat-mp -- 微信公众号管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-service -- 业务逻辑<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    └── zheng-wechat-mp-admin -- 后台管理[端口:5551]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-app -- 微信小程序后台<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-api -- API接口总线系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-common -- api系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-api-server -- api系统服务端[端口:6666]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-oss -- 对象存储系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-web -- 前台接口[端口:7771]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-oss-admin -- 后台管理[端口:7772]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-message -- 实时通知系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-server -- 服务端[端口:8881,SocketIO端口:8882]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-message-client -- 客户端<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-shop -- 电子商务系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />└── zheng-demo -- 示例模块(包含一些示例代码等)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     └── zheng-demo-web -- 演示示例[端口:9999]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />
  架构图
  
  架构图模块依赖
  
  模块依赖环境搭建开发工具:开发环境:演示地址
  演示地址:[1]
  预览图
  
  
  
  数据模型
  
  数据库模型拓扑图
  
  拓扑图
  项目源码,怎么领取?
  
  源码获取
  
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!</p>
  扫码下方二维码,后台回复【宝藏】即可获取所有系统
  
  欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️<br mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="outline: 0px;line-height: 25.6px;" /><p data-tool="mdnice编辑器" mp-original-font-size="16" mp-original-line-height="28" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.544px;color: rgb(74, 74, 74);line-height: 28px;font-size: 16px;">在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!</p>
  最后,整理了300多套项目,赠送读者。扫码下方二维码,后台回复【赚钱】即可获取。
  <p style="text-align: center;"></p>
  --END-- 查看全部

  一款神仙儿宝藏级微服务开源项目,吊到炸裂!
  大家好,我是Java架构师
  今天,推荐一个宝藏级微服务开源项目。我第一次使用就有点上头,爱不释手,必须要推荐给大家。
  上次是谁要的宝藏级微服务开源项目啊,我帮你找到了。
  这是我目前见过最好的宝藏级微服务开源项目。功能完整,代码结构清晰。值得推荐。 项目介绍
  前几天有粉丝留言,正在学习微服务,想让我推荐一个微服务学习项目。这次我拿出了压箱底的收藏了,一个宝藏级微服务开源项目,炸裂!
  前言
  zheng项目不仅仅是一个开发架构,而是努力打造一套从前端模板-基础框架-分布式架构-开源项目-持续集成-自动化部署-系统监测-无缝升级的全方位J2EE企业级开发解决方案。扩展:
  项目介绍
  基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公共微服务服务模块:内容管理、支付中心、用户管理(包括第三方)、微信平台、存储系统、配置中心、日志分析、任务和通知等,支持服务治理、监控和追踪,努力为中小型企业打造全方位J2EE企业级开发解决方案。
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!赶快收藏吧...</p>
  组织结构
  zheng<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-common -- SSM框架公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-admin -- 后台管理模板<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ui -- 前台thymeleaf模板[端口:1000]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-config -- 配置中心[端口:1001]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-upms -- 用户权限管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-common -- upms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-client -- 集成upms依赖包,提供单点认证、授权、统一会话管理<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-upms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-upms-server -- 用户权限系统及SSO服务端[端口:1111]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-cms -- 内容管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-common -- cms系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-search -- 搜索服务[端口:2221]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-admin -- 后台管理[端口:2222]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-cms-job -- 消息队列、任务调度等[端口:2223]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-cms-web -- 网站前台[端口:2224]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-pay -- 支付系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-common -- pay系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-pay-admin -- 后台管理[端口:3331]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-pay-web -- 演示示例[端口:3332]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-ucenter -- 用户系统(包括第三方登录)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-common -- ucenter系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-ucenter-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-web -- 网站前台[端口:4441]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-wechat -- 微信系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-wechat-mp -- 微信公众号管理系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-dao -- 代码生成模块,无需开发<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    ├── zheng-wechat-mp-service -- 业务逻辑<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    |    └── zheng-wechat-mp-admin -- 后台管理[端口:5551]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-ucenter-app -- 微信小程序后台<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-api -- API接口总线系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-common -- api系统公共模块<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-api-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-api-server -- api系统服务端[端口:6666]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-oss -- 对象存储系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-oss-web -- 前台接口[端口:7771]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-oss-admin -- 后台管理[端口:7772]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-message -- 实时通知系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-sdk -- 开发工具包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    ├── zheng-message-server -- 服务端[端口:8881,SocketIO端口:8882]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />|    └── zheng-message-client -- 客户端<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />├── zheng-shop -- 电子商务系统<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />└── zheng-demo -- 示例模块(包含一些示例代码等)<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-api -- rpc接口包<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     ├── zheng-demo-rpc-service -- rpc服务提供者<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />     └── zheng-demo-web -- 演示示例[端口:9999]<br mp-original-font-size="12" mp-original-line-height="19" style="outline: 0px;line-height: 19px;" />
  架构图
  
  架构图模块依赖
  
  模块依赖环境搭建开发工具:开发环境:演示地址
  演示地址:[1]
  预览图
  
  
  
  数据模型
  
  数据库模型拓扑图
  
  拓扑图
  项目源码,怎么领取?
  
  源码获取
  
  <p mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="margin-right: 8px;margin-left: 8px;outline: 0px;color: rgb(34, 34, 34);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;visibility: visible;text-align: center;line-height: 25.6px;">
  牛逼啊!接私活必备的 N 个开源项目!</p>
  扫码下方二维码,后台回复【宝藏】即可获取所有系统
  
  欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️<br mp-original-font-size="17" mp-original-line-height="25.600000381469727" style="outline: 0px;line-height: 25.6px;" /><p data-tool="mdnice编辑器" mp-original-font-size="16" mp-original-line-height="28" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.544px;color: rgb(74, 74, 74);line-height: 28px;font-size: 16px;">在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!</p>
  最后,整理了300多套项目,赠送读者。扫码下方二维码,后台回复【赚钱】即可获取。
  <p style="text-align: center;"></p>
  --END--

官方客服QQ群

微信人工客服

QQ人工客服


线