html5 学习网站,简单建站的网站,seo优化策略,空间平面的网页设计素材文章目录 概要elctron 生命周期及窗口应用主进程与渲染进程交互技术细节electron 中需要注意的安全问题 概要 
一、Electron简介 
Electron是一个开源框架#xff0c;它允许开发者使用JavaScript、HTML和CSS构建跨平台的桌面应用程序。它基于Chromium#xff08;谷歌浏览器的… 文章目录 概要elctron 生命周期及窗口应用主进程与渲染进程交互技术细节electron 中需要注意的安全问题  概要 
一、Electron简介 
Electron是一个开源框架它允许开发者使用JavaScript、HTML和CSS构建跨平台的桌面应用程序。它基于Chromium谷歌浏览器的开源核心和Node.js这意味着开发者可以利用前端和后端的技术来创建功能丰富的桌面软件像著名的Visual Studio Code就是用Electron构建的。 
二、应用安装 
开发环境搭建 首先需要安装Node.js因为Electron依赖于Node.js的模块管理和脚本运行环境。可以从Node.js官方网站https://nodejs.org/下载适合操作系统的安装包进行安装。安装完成后通过命令行工具如Windows的命令提示符或PowerShellMac和Linux的终端输入node -v和npm -v来验证是否安装成功这两个命令分别会显示Node.js和npmNode.js的包管理器的版本号。然后通过npm来安装Electron。可以在项目目录下运行npm install electron命令来安装Electron。也可以使用yarn另一种流行的包管理器通过yarn add electron进行安装。 创建和运行基本应用 安装好Electron后可以创建一个简单的Electron应用。首先创建一个项目目录在目录下创建main.js主进程文件、index.html渲染进程文件和package.json项目配置文件。在main.js中代码示例如下  
const { app, BrowserWindow }  require(electron);
function createWindow() {const win  new BrowserWindow({width: 800,height: 600});win.loadFile(index.html);
}
app.whenReady().then(()  {createWindow();app.on(activate, ()  {if (BrowserWindow.getAllWindows().length  0) {createWindow();}});
});
app.on(window - all - closed, ()  {if (process.platform! darwin) {app.quit();}
});在index.html中可以编写简单的HTML代码如 
!DOCTYPE html
html
headmeta charsetUTF - 8titleMy Electron App/title
/head
bodyh1Hello, Electron!/h1
/body
/html在package.json中添加启动脚本例如 
{name: my - electron - app,version: 1.0.0,main: main.js,scripts: {start: electron.},devDependencies: {electron: ^27.0.0}
}然后在项目目录下通过命令行运行npm start或者yarn start就可以启动应用程序看到一个简单的窗口显示“Hello, Electron!”。 
三、页面交互 
主进程和渲染进程通信 Electron应用有主进程和渲染进程之分。主进程负责管理应用的生命周期、创建和管理窗口等渲染进程负责展示页面内容。它们之间需要通信来实现功能。例如从渲染进程向主进程发送消息。在渲染进程的index.html中添加一个按钮  
button idmyButtonSend Message to Main/button在对应的JavaScript代码可以在index.html中通过script标签引入或者作为一个单独的.js文件引入中 
const { ipcRenderer }  require(electron);
const myButton  document.getElementById(myButton);
myButton.addEventListener(click, ()  {ipcRenderer.send(message - from - renderer, This is a message from the renderer process);
});在主进程main.js中接收消息 
const { ipcMain }  require(electron);
ipcMain.on(message - from - renderer, (event, arg)  {console.log(arg); // 可以在这里根据接收到的消息进行其他操作比如更新窗口标题等const currentWindow  BrowserWindow.getFocusedWindow();if (currentWindow) {currentWindow.setTitle(arg);}
});渲染进程内交互 在渲染进程内部就像普通的网页开发一样可以使用JavaScript来处理各种交互。例如实现一个简单的表单提交功能。在index.html中添加一个表单  
form idmyForminput typetext idinputField /button typesubmitSubmit/button
/form对应的JavaScript代码 
const myForm  document.getElementById(myForm);
myForm.addEventListener(submit, (e)  {e.preventDefault();const inputValue  document.getElementById(inputField).value;console.log(Input value:, inputValue);// 可以在这里进行更多关于输入值的处理比如显示在页面其他地方等
});四、打包部署安装 
打包工具选择 常用的Electron打包工具是Electron - Packager和Electron - Builder。Electron - Packager可以将应用程序打包成特定平台的可执行文件格式。Electron - Builder功能更强大它支持多种平台并且可以生成安装包、自动更新等功能。以Electron - Builder为例首先需要安装它。在项目目录下运行npm install electron - builder - - save - dev或者yarn add electron - builder - - dev。 配置打包脚本 在package.json中配置打包脚本。例如  
{name: my - electron - app,version: 1.0.0,main: main.js,scripts: {start: electron.,package: electron - builder},build: {appId: com.example.my - electron - app,productName: My Electron App,mac: {category: public.app - category.utilities},win: {target: [nsis]}},devDependencies: {electron: ^27.0.0,electron - builder: ^23.6.0}
}这里配置了应用的标识appId、产品名称productName以及针对Mac和Windows的一些打包选项如在Windows下使用NSISNullsoft Scriptable Install System来创建安装程序。 
打包操作 配置好后在项目目录下通过命令行运行npm run package或者yarn package就可以开始打包。打包完成后在项目的dist目录具体位置可能根据配置有所不同下会生成可执行文件或安装包。对于Windows会得到一个.exe安装程序或者解压后可直接运行的文件对于Mac会得到一个.app文件。 部署和安装 对于打包好的应用可以通过各种方式进行部署。可以将安装包发布到官方网站、软件下载平台等。用户下载安装包后像安装普通软件一样进行安装。在Windows上双击.exe安装程序按照安装向导的步骤进行安装在Mac上将.app文件拖移到“Applications”文件夹或者直接双击运行来安装。  
elctron 生命周期及窗口应用 
管理生命周期 app模块的使用在Electron中app模块是控制应用程序生命周期的核心。例如app.whenReady()方法用于在Electron初始化完成后执行一些操作。以下是一个典型的main.js文件中对应用生命周期管理的示例  
const { app }  require(electron);
function createWindow() {// 创建窗口的代码将在后面介绍
}
// 当Electron初始化完成后创建窗口
app.whenReady().then(()  {createWindow();// 当应用被激活时例如从Dock或任务栏重新打开如果没有窗口则创建一个app.on(activate, ()  {if (BrowserWindow.getAllWindows().length  0) {createWindow();}});
});
// 当所有窗口都关闭时在非macOS平台上退出应用
app.on(window - all - closed, ()  {if (process.platform! darwin) {app.quit();}
});在这个例子中app.whenReady()确保在Electron准备好后才创建窗口。app.on(activate)监听应用激活事件app.on(window - all - closed)监听所有窗口关闭的事件根据平台决定是否退出应用。在macOS上即使所有窗口关闭应用通常也会保留在Dock中直到用户明确退出。 
创建窗口 BrowserWindow类的应用使用BrowserWindow类来创建窗口。可以设置窗口的各种属性如大小、标题、是否可调整大小等。示例代码  
const { app, BrowserWindow }  require(electron);
function createWindow() {const win  new BrowserWindow({width: 800,height: 600,title: My Electron App,webPreferences: {nodeIntegration: true}});win.loadFile(index.html);return win;
}在这里创建了一个BrowserWindow实例设置了窗口的宽度为800像素、高度为600像素标题为My Electron App。webPreferences中的nodeIntegration: true允许在渲染进程中使用Node.js的功能。然后通过win.loadFile(index.html)加载了一个HTML文件作为窗口的内容。这个createWindow函数可以返回创建的窗口实例方便后续对窗口进行管理。 
管理窗口 获取和操作窗口实例可以使用BrowserWindow.getAllWindows()获取所有打开的窗口实例列表BrowserWindow.getFocusedWindow()获取当前获得焦点的窗口。例如在主进程中修改窗口标题  
const { ipcMain, BrowserWindow }  require(electron);
ipcMain.on(change - window - title, (event, newTitle)  {const currentWindow  BrowserWindow.getFocusedWindow();if (currentWindow) {currentWindow.setTitle(newTitle);}
});这个例子中通过ipcMain接收一个名为change - window - title的消息当接收到消息后获取当前获得焦点的窗口如果有并将其标题修改为消息中传递的新标题。还可以对窗口进行其他操作如最小化、最大化、关闭等。例如 
const { BrowserWindow }  require(electron);
const win  BrowserWindow.getFocusedWindow();
if (win) {win.minimize(); // 最小化窗口win.maximize(); // 最大化窗口win.close(); // 关闭窗口
}主进程与渲染进程交互 Electron创建窗口 基础窗口创建 在Electron的主进程通常是main.js文件中使用BrowserWindow类来创建窗口。首先需要引入BrowserWindow和app模块如下所示   
const { app, BrowserWindow }  require(electron);然后定义一个函数来创建窗口。在这个函数中通过new BrowserWindow()来实例化一个窗口对象并传入一个配置对象来设置窗口的属性。例如 
function createWindow() {const win  new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true}});win.loadFile(index.html);return win;
}在上述代码中创建的窗口宽度为800像素高度为600像素。webPreferences中的nodeIntegration: true是一个重要的设置它允许在渲染进程加载的HTML页面中使用Node.js的功能。win.loadFile(index.html)这一行是将一个本地的HTML文件加载到窗口中作为显示内容。这个index.html文件就是渲染进程的入口文件。 多窗口创建 如果需要创建多个窗口可以在适当的事件触发时调用createWindow函数。例如当用户点击一个按钮或者满足某个条件时创建新窗口。假设在主进程中有一个事件监听器当接收到一个特定的IPC进程间通信消息时创建新窗口   
const { ipcMain }  require(electron);
ipcMain.on(open - new - window, (event, arg)  {const newWin  createWindow();// 可以在这里对新窗口进行进一步的操作如设置位置等newWin.setPosition(100, 100);
});这里当主进程接收到名为open - new - window的IPC消息时就会调用createWindow函数创建一个新的窗口并将其位置设置为横坐标100像素、纵坐标100像素的位置。 主进程与渲染进程交互实例 从渲染进程发送消息到主进程 在渲染进程index.html及其关联的JavaScript文件中首先需要引入ipcRenderer模块。假设index.html中有一个按钮点击这个按钮就向主进程发送消息   
!DOCTYPE html
html
headmeta charsetUTF - 8
/head
bodybutton idsendMessageButtonSend Message to Main/buttonscriptconst { ipcRenderer }  require(electron);const sendMessageButton  document.getElementById(sendMessageButton);sendMessageButton.addEventListener(click, ()  {ipcRenderer.send(message - from - renderer, This is a test message);});/script
/body
/html在上述代码中ipcRenderer.send()方法用于发送消息。第一个参数message - from - renderer是一个自定义的通道名称用于在主进程中识别消息来源第二个参数This is a test message是要发送的实际消息内容。 在主进程中接收并处理消息 在主进程main.js中需要使用ipcMain模块来接收消息。代码如下   
const { ipcMain }  require(electron);
ipcMain.on(message - from - renderer, (event, arg)  {console.log(Received message from renderer:, arg);// 可以根据接收到的消息进行各种操作如修改窗口属性等const currentWindow  BrowserWindow.getFocusedWindow();if (currentWindow) {currentWindow.setTitle(arg);}
});这里ipcMain.on()方法监听名为message - from - renderer的通道消息。当接收到消息时会在控制台打印消息内容并获取当前获得焦点的窗口如果有将其标题设置为接收到的消息内容。 从主进程发送消息到渲染进程 在主进程中发送消息到渲染进程首先要获取窗口对应的WebContents对象。例如在主进程中有一个定时器每隔一段时间就向渲染进程发送消息   
const { app, BrowserWindow }  require(electron);
function createWindow() {const win  new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true}});win.loadFile(index.html);// 定时器每隔5秒发送一次消息setInterval(()  {const webContents  win.webContents;webContents.send(message - from - main, This is a message from the main process);}, 5000);return win;
}这里通过win.webContents.send()方法发送消息。message - from - main是通道名称This is a message from the main process是消息内容。 在渲染进程中接收并处理消息 在渲染进程中需要使用ipcRenderer来接收主进程发送的消息。代码如下   
const { ipcRenderer }  require(electron);
ipcRenderer.on(message - from - main, (event, arg)  {console.log(Received message from main:, arg);// 可以根据消息进行更新页面内容等操作const messageElement  document.createElement(p);messageElement.textContent  arg;document.body.appendChild(messageElement);
});当渲染进程接收到名为message - from - main的消息时会在控制台打印消息内容并在页面中创建一个新的p标签将消息内容添加到标签中然后将标签添加到页面的body元素中从而在页面上显示主进程发送的消息。 
技术细节 
在HTML中直接引用Electron不推荐用于正式开发 在开发初期的快速原型阶段或者非常小型的应用场景下可能会直接在HTML文件渲染进程中引用Electron相关模块来进行简单的功能测试。例如在index.html文件中通过script标签直接引入Electron的ipcRenderer模块来实现主进程和渲染进程之间的简单通信。示例代码如下  
!DOCTYPE html
html
headmeta charsetUTF - 8
/head
bodybutton idsendMessageButtonSend Message to Main/buttonscript// 直接引入Electron的ipcRenderer模块const { ipcRenderer }  require(electron);const sendMessageButton  document.getElementById(sendMessageButton);sendMessageButton.addEventListener(click, ()  {ipcRenderer.send(message - from - renderer, This is a test message);});/script
/body
/html这种方式虽然简单直接但存在一些问题。比如它没有很好地遵循模块加载的最佳实践并且如果在复杂的项目中可能会导致代码难以维护和管理。另外在一些严格的安全策略下这种直接引用可能会受到限制。 
在正式开发中的更好实践 预加载脚本Preload Scripts 在正式开发中通常会使用预加载脚本。预加载脚本是一个在渲染进程加载之前运行的脚本它运行在一个特殊的环境中可以访问Electron的主进程和渲染进程的一些功能。首先创建一个预加载脚本文件例如preload.js在这个文件中可以进行一些初始化操作比如将主进程的功能封装并暴露给渲染进程。示例代码如下   
const { contextBridge, ipcRenderer }  require(electron);
// 暴露一个名为sendMessageToMain的函数给渲染进程
contextBridge.exposeInheritedObject(electronAPI, {sendMessageToMain: (message)  {ipcRenderer.send(message - from - renderer, message);}
});然后在创建BrowserWindow时指定预加载脚本。在main.js文件中 
const { app, BrowserWindow }  require(electron);
function createWindow() {const win  new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, preload.js)}});win.loadFile(index.html);return win;
}在index.html文件中就可以通过window.electronAPI.sendMessageToMain来调用这个函数发送消息到主进程这样的方式更加安全和易于维护。模块打包和构建工具 在正式开发中还会使用模块打包和构建工具如Webpack或Rollup。这些工具可以帮助管理和打包JavaScript代码包括Electron相关的代码。例如使用Webpack时可以将Electron相关的代码作为一个模块进行管理通过配置webpack.config.js文件来处理不同的入口文件包括主进程的main.js和渲染进程的index.html相关的JavaScript文件。可以将Electron模块的引用和其他依赖一起打包并且可以进行代码优化、压缩等操作提高应用的性能和可维护性。 代码分离和分层架构 正式开发通常会采用代码分离和分层架构。将Electron相关的功能代码如主进程的生命周期管理、窗口创建和进程间通信等与具体的业务逻辑和页面展示代码在渲染进程中分开。例如在一个大型的Electron应用中可能会有一个专门的electron-services文件夹里面存放主进程相关的服务代码如窗口管理服务、文件系统服务利用Electron的fs模块等。在渲染进程中通过前面提到的预加载脚本或者其他通信机制来调用这些服务从而实现清晰的架构和更好的代码复用。  
electron 中需要注意的安全问题 Electron安全性概述 Electron应用的安全性是一个重要的考虑因素因为它结合了Web技术HTML、CSS、JavaScript和本地系统访问权限通过Node.js。与传统的纯Web应用相比Electron应用有更多潜在的安全风险因为它们可以访问本地文件系统、操作系统功能等。不过Electron本身也提供了一些机制来帮助开发者构建安全的应用。  正式开发中需要注意的安全问题及应对措施 进程间通信IPC安全 问题主进程和渲染进程之间的通信通道如果没有正确保护可能会被恶意利用。例如攻击者可能会尝试在渲染进程中发送恶意指令到主进程从而获取敏感信息或者执行有害操作。应对措施 对IPC消息进行验证和过滤。在主进程接收渲染进程消息时检查消息的来源和内容是否合法。例如只接受来自已知渲染进程且符合预定义格式的消息。使用contextBridge来安全地暴露主进程的API给渲染进程。通过contextBridge.exposeInheritedObject可以精确控制暴露给渲染进程的功能避免过度暴露可能导致安全风险的主进程功能。以下是一个示例    
// 在预加载脚本preload.js中
const { contextBridge, ipcRenderer }  require(electron);
contextBridge.exposeInheritedObject(electronAPI, {// 只暴露一个安全的函数用于发送消息到主进程sendMessageToMain: (message)  {ipcRenderer.send(message - from - renderer, message);}
});渲染进程中的脚本安全 问题渲染进程中的JavaScript代码可能会受到跨站脚本攻击XSS。如果应用加载了不可信的外部内容或者用户输入没有得到正确处理就可能导致恶意脚本在渲染进程中执行。应对措施 对用户输入进行严格的过滤和转义。在将用户输入插入到HTML页面如用于显示用户评论、表单提交内容等场景之前使用合适的函数进行转义防止恶意脚本注入。例如在JavaScript中使用DOMParser来安全地解析和处理HTML内容。避免使用eval()函数和Function()构造函数因为它们可以执行任意字符串作为JavaScript代码这是XSS攻击的一个常见入口点。如果必须使用要确保输入内容是完全可信的。限制对外部资源的加载。如果应用不需要加载外部脚本或者样式表应该避免加载。如果需要加载要确保来源是可信的并使用内容安全策略CSP来限制脚本的执行范围。例如可以在HTML页面的meta标签中设置CSP如下   
meta http-equivContent-Security-Policy contentdefault-srcself; script
-srcself本地文件系统访问安全 问题由于Electron应用可以通过Node.js访问本地文件系统这可能会导致用户文件的泄露或者被恶意篡改。如果应用没有正确地限制文件访问权限攻击者可能会利用这个漏洞获取敏感文件如用户的文档、配置文件等。应对措施 最小化文件访问权限。只在必要时才使用Node.js的fs模块访问本地文件系统并且只访问应用需要的特定文件和目录。例如如果应用只需要读取一个特定的配置文件可以明确指定该文件的路径而不是允许访问整个文件系统。对用户操作进行权限验证。当用户尝试通过应用执行文件操作如保存、删除文件等时要验证用户是否有相应的权限。这可以通过操作系统提供的用户认证机制或者应用内部的权限管理系统来实现。加密敏感文件。如果应用存储了敏感的用户数据如密码、密钥等在存储到本地文件系统之前应该使用适当的加密算法进行加密。当需要访问这些文件时再进行解密。例如可以使用crypto模块Node.js内置模块来进行文件加密和解密操作。  网络访问安全 问题Electron应用在进行网络访问时可能会受到中间人攻击、恶意网络请求等安全威胁。例如应用可能会发送用户的敏感信息如登录凭证没有经过加密的网络请求。应对措施 使用安全的网络协议。对于涉及用户敏感信息的网络通信如登录、支付等操作应该使用HTTPS协议而不是HTTP。可以通过检查服务器证书的有效性来确保通信的安全性。对网络请求进行限制。只允许应用向已知的、可信的服务器发送请求。可以通过配置网络请求的白名单或者使用代理服务器来限制请求的目标。防止跨域攻击。如果应用与多个不同域的服务器进行交互要注意防范跨域攻击。可以通过设置合适的跨域策略如服务器端设置Access-Control-Allow-Origin头和在客户端正确处理跨域请求来避免安全问题。   文章转载自: http://www.morning.thlr.cn.gov.cn.thlr.cn http://www.morning.gpkjx.cn.gov.cn.gpkjx.cn http://www.morning.xdmsq.cn.gov.cn.xdmsq.cn http://www.morning.kwxr.cn.gov.cn.kwxr.cn http://www.morning.ggnkt.cn.gov.cn.ggnkt.cn http://www.morning.nyqnk.cn.gov.cn.nyqnk.cn http://www.morning.qtrlh.cn.gov.cn.qtrlh.cn http://www.morning.rkxk.cn.gov.cn.rkxk.cn http://www.morning.hcgbm.cn.gov.cn.hcgbm.cn http://www.morning.jbtzx.cn.gov.cn.jbtzx.cn http://www.morning.kqpq.cn.gov.cn.kqpq.cn http://www.morning.nlwrg.cn.gov.cn.nlwrg.cn http://www.morning.btqrz.cn.gov.cn.btqrz.cn http://www.morning.xplng.cn.gov.cn.xplng.cn http://www.morning.gnlyq.cn.gov.cn.gnlyq.cn http://www.morning.qgxnw.cn.gov.cn.qgxnw.cn http://www.morning.ydgzj.cn.gov.cn.ydgzj.cn http://www.morning.tqqfj.cn.gov.cn.tqqfj.cn http://www.morning.chkfp.cn.gov.cn.chkfp.cn http://www.morning.skdhm.cn.gov.cn.skdhm.cn http://www.morning.mzhgf.cn.gov.cn.mzhgf.cn http://www.morning.xqxlb.cn.gov.cn.xqxlb.cn http://www.morning.qfkxj.cn.gov.cn.qfkxj.cn http://www.morning.mtcnl.cn.gov.cn.mtcnl.cn http://www.morning.rmfh.cn.gov.cn.rmfh.cn http://www.morning.fwzjs.cn.gov.cn.fwzjs.cn http://www.morning.fswml.cn.gov.cn.fswml.cn http://www.morning.rpdmj.cn.gov.cn.rpdmj.cn http://www.morning.tkcz.cn.gov.cn.tkcz.cn http://www.morning.nrfqd.cn.gov.cn.nrfqd.cn http://www.morning.cpkcq.cn.gov.cn.cpkcq.cn http://www.morning.nyqb.cn.gov.cn.nyqb.cn http://www.morning.fhddr.cn.gov.cn.fhddr.cn http://www.morning.cfcpb.cn.gov.cn.cfcpb.cn http://www.morning.zdnrb.cn.gov.cn.zdnrb.cn http://www.morning.rxhsm.cn.gov.cn.rxhsm.cn http://www.morning.4q9h.cn.gov.cn.4q9h.cn http://www.morning.hybmz.cn.gov.cn.hybmz.cn http://www.morning.ggnkt.cn.gov.cn.ggnkt.cn http://www.morning.mlzyx.cn.gov.cn.mlzyx.cn http://www.morning.zdgp.cn.gov.cn.zdgp.cn http://www.morning.mlpmf.cn.gov.cn.mlpmf.cn http://www.morning.kdjtt.cn.gov.cn.kdjtt.cn http://www.morning.lnfkd.cn.gov.cn.lnfkd.cn http://www.morning.mxftp.com.gov.cn.mxftp.com http://www.morning.bnxnq.cn.gov.cn.bnxnq.cn http://www.morning.zfgh.cn.gov.cn.zfgh.cn http://www.morning.ynjhk.cn.gov.cn.ynjhk.cn http://www.morning.hqmfn.cn.gov.cn.hqmfn.cn http://www.morning.hxwrs.cn.gov.cn.hxwrs.cn http://www.morning.pcgrq.cn.gov.cn.pcgrq.cn http://www.morning.lswgs.cn.gov.cn.lswgs.cn http://www.morning.jbkcs.cn.gov.cn.jbkcs.cn http://www.morning.fhlfp.cn.gov.cn.fhlfp.cn http://www.morning.nqnqz.cn.gov.cn.nqnqz.cn http://www.morning.rryny.cn.gov.cn.rryny.cn http://www.morning.hhxwr.cn.gov.cn.hhxwr.cn http://www.morning.rxwfg.cn.gov.cn.rxwfg.cn http://www.morning.wnqbf.cn.gov.cn.wnqbf.cn http://www.morning.zxhpx.cn.gov.cn.zxhpx.cn http://www.morning.qhkdt.cn.gov.cn.qhkdt.cn http://www.morning.bsgfl.cn.gov.cn.bsgfl.cn http://www.morning.bppml.cn.gov.cn.bppml.cn http://www.morning.wrcgy.cn.gov.cn.wrcgy.cn http://www.morning.wnzgm.cn.gov.cn.wnzgm.cn http://www.morning.pzlcd.cn.gov.cn.pzlcd.cn http://www.morning.txfxy.cn.gov.cn.txfxy.cn http://www.morning.rtlth.cn.gov.cn.rtlth.cn http://www.morning.mzhgf.cn.gov.cn.mzhgf.cn http://www.morning.fnywn.cn.gov.cn.fnywn.cn http://www.morning.nzsdr.cn.gov.cn.nzsdr.cn http://www.morning.gwwtm.cn.gov.cn.gwwtm.cn http://www.morning.qrcxh.cn.gov.cn.qrcxh.cn http://www.morning.whpsl.cn.gov.cn.whpsl.cn http://www.morning.tkchg.cn.gov.cn.tkchg.cn http://www.morning.zqbrd.cn.gov.cn.zqbrd.cn http://www.morning.dpqwq.cn.gov.cn.dpqwq.cn http://www.morning.sooong.com.gov.cn.sooong.com http://www.morning.rwpfb.cn.gov.cn.rwpfb.cn http://www.morning.kdfqx.cn.gov.cn.kdfqx.cn