当前位置: 首页 > news >正文

快速搭建网站的工具有哪些家里公网宽带做网站要备案么

快速搭建网站的工具有哪些,家里公网宽带做网站要备案么,梅州建站方法,怎么快速搭建网站api接口加密 1.为什么需要api接口加密呢#xff1f; 1.防止爬虫 2.防止数据被串改 3.确保数据安全 2.如何实现接口加密呢#xff1f; 3.我们可以使用哪些加密算法来加密呢#xff1f; AES 密码学中的高级加密标准#xff08;Advanced Encryption Standard#xff0c;…api接口加密 1.为什么需要api接口加密呢 1.防止爬虫 2.防止数据被串改 3.确保数据安全 2.如何实现接口加密呢 3.我们可以使用哪些加密算法来加密呢 AES 密码学中的高级加密标准Advanced Encryption StandardAES又称Rijndael加密法是美国联邦政府采用的一种区块加密标准。 SM4 SM4.0原名SMS4.0是中华人民共和国政府采用的一种分组密码标准由国家密码管理局于2012年3月21日发布。相关标准为“GM/T 0002-2012《SM4分组密码算法》原SMS4分组密码算法”。在商用密码体系中SM4主要用于数据加密其算法公开分组长度与密钥长度均为128bit加密算法与密钥扩展算法都采用32轮非线性迭代结构S盒为固定的8比特输入8比特输出。SM4.0中的指令长度被提升到大于64K即64×1024的水平这是SM 3.0规格渲染指令长度允许大于512的128倍。 4.具体实现 4.1后端 在这之前我们先了解一个类RequestBodyAdviceAdapter主要通过该类实现~ RequestBodyAdviceAdapter 官网解释RequestBodyAdviceAdapter (Spring Framework 6.2.1 API) ‌RequestBodyAdviceAdapter‌是Spring MVC中用于增强请求体处理的一个工具类它实现了RequestBodyAdvice接口。RequestBodyAdviceAdapter提供了三个主要方法beforeBodyRead、afterBodyRead和handleEmptyBody。 ‌beforeBodyRead‌这个方法在请求体被读取之前调用主要用于预处理请求体。默认实现是直接返回传入的HttpInputMessage对象。 ‌afterBodyRead‌在请求体被读取并转换为对象之后调用用于对读取到的对象进行进一步处理。默认实现是直接返回转换后的对象。 ‌handleEmptyBody‌当请求体为空时调用用于处理这种情况。默认实现是直接返回null。 代码实现 这里我们使用类似Aop的思想实现定义对应的注解 Retention(RetentionPolicy.RUNTIME) Target({ElementType.TYPE, ElementType.METHOD}) public interface ApiDecrypt { //解密 } Retention(RetentionPolicy.RUNTIME) Target({ElementType.TYPE, ElementType.METHOD}) public interface ApiEncrypt {//加密 } ​ Slf4j ControllerAdvice public class DecryptRequestAdvice extends RequestBodyAdviceAdapter { ​private static final String ENCODING UTF-8; ​Resourceprivate ApiEncryptService apiEncryptService; ​Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class? extends HttpMessageConverter? converterType) {return methodParameter.hasMethodAnnotation(ApiDecrypt.class) || methodParameter.hasParameterAnnotation(ApiDecrypt.class)|| methodParameter.getContainingClass().isAnnotationPresent(ApiDecrypt.class);} ​Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,Type targetType, Class? extends HttpMessageConverter? converterType) {try {String bodyStr IOUtils.toString(inputMessage.getBody(), ENCODING);ApiEncryptForm apiEncryptForm JSONObject.parseObject(bodyStr, ApiEncryptForm.class);if (StrUtil.isEmpty(apiEncryptForm.getEncryptData())) {return inputMessage;}String decrypt apiEncryptService.decrypt(apiEncryptForm.getEncryptData());return new DecryptHttpInputMessage(inputMessage.getHeaders(), IOUtils.toInputStream(decrypt, ENCODING));} catch (Exception e) {return inputMessage;} ​} ​Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class? extends HttpMessageConverter? converterType) {return body;} ​Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class? extends HttpMessageConverter? converterType) {return body;} ​static class DecryptHttpInputMessage implements HttpInputMessage {private final HttpHeaders headers; ​private final InputStream body; ​public DecryptHttpInputMessage(HttpHeaders headers, InputStream body) {this.headers headers;this.body body;} ​Overridepublic InputStream getBody() {return body;} ​Overridepublic HttpHeaders getHeaders() {return headers;}} ​ } Slf4j ControllerAdvice public class EncryptResponseAdvice implements ResponseBodyAdviceResponseDTO { ​Resourceprivate ApiEncryptService apiEncryptService; ​Resourceprivate ObjectMapper objectMapper; ​Overridepublic boolean supports(MethodParameter returnType, Class? extends HttpMessageConverter? converterType) {return returnType.hasMethodAnnotation(ApiEncrypt.class) || returnType.getContainingClass().isAnnotationPresent(ApiEncrypt.class);} ​Overridepublic ResponseDTO beforeBodyWrite(ResponseDTO body, MethodParameter returnType, MediaType selectedContentType, Class? extends HttpMessageConverter? selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if (body.getData() null) {return body;} ​String encrypt null;try {encrypt apiEncryptService.encrypt(objectMapper.writeValueAsString(body.getData()));} catch (JsonProcessingException e) {throw new RuntimeException(e);}body.setData(encrypt);body.setDataType(DataTypeEnum.ENCRYPT.getValue());return body;} } 实现类 /*** AES 加密和解密* 1、AES加密算法支持三种密钥长度128位、192位和256位这里选择128位* 2、AES 要求秘钥为 128bit转化字节为 16个字节* 3、js前端使用 UCS-2 或者 UTF-16 编码字母、数字、特殊符号等 占用1个字节* 4、所以秘钥Key 组成为字母、数字、特殊符号 一共16个即可*/ Slf4j public class ApiEncryptServiceAesImpl implements ApiEncryptService { ​private static final String CHARSET UTF-8; ​private static final String AES_KEY 1024lab__1024lab; ​static {Security.addProvider(new BouncyCastleProvider());} ​Overridepublic String encrypt(String data) {try {// AES 加密 并转为 base64AES aes new AES(hexToBytes(stringToHex(AES_KEY)));return aes.encryptBase64(data);} catch (Exception e) {log.error(e.getMessage(), e);return StringConst.EMPTY;}} ​Overridepublic String decrypt(String data) {try {// 第一步 Base64 解码byte[] base64Decode Base64.getDecoder().decode(data);// 第二步 AES 解密AES aes new AES(hexToBytes(stringToHex(AES_KEY)));byte[] decryptedBytes aes.decrypt(base64Decode);return new String(decryptedBytes, CHARSET);} catch (Exception e) {log.error(e.getMessage(), e);return StringConst.EMPTY;}} ​/*** 16 进制串转字节数组** param hex 16进制字符串* return byte数组*/public static byte[] hexToBytes(String hex) {int length hex.length();byte[] result;if (length % 2 1) {length;result new byte[(length / 2)];hex 0 hex;} else {result new byte[(length / 2)];}int j 0;for (int i 0; i length; i 2) {result[j] hexToByte(hex.substring(i, i 2));j;}return result;} ​public static String stringToHex(String input) {char[] chars input.toCharArray();StringBuilder hex new StringBuilder();for (char c : chars) {hex.append(Integer.toHexString((int) c));}return hex.toString();} ​/*** 16 进制字符转字节** param hex 16进制字符 0x00到0xFF* return byte*/private static byte hexToByte(String hex) {return (byte) Integer.parseInt(hex, 16);} ​public static void main(String[] args) { //       System.out.println(new ApiEncryptServiceAesImpl().encrypt({\name\:\chen\,\age\:18}));System.out.println(new ApiEncryptServiceAesImpl().decrypt(MWFjZTI3MDA0ZDcxY2RlM2U4YTY5NDU3MjE3MmE0YzlhOTI0OTVhOTBiM2VmYzYwZjgxZTlmMjRmNDVkMWNlMg));} } ​ ​ Slf4j Service public class ApiEncryptServiceSmImpl implements ApiEncryptService { ​private static final String CHARSET UTF-8;private static final String SM4_KEY 1024lab__1024lab; ​static {Security.addProvider(new BouncyCastleProvider());} ​ ​Overridepublic String encrypt(String data) {try { ​// 第一步 SM4 加密SM4 sm4 new SM4(hexToBytes(stringToHex(SM4_KEY)));String encryptHex sm4.encryptHex(data); ​// 第二步 Base64 编码return new String(Base64.getEncoder().encode(encryptHex.getBytes(CHARSET)), CHARSET); ​} catch (Exception e) {log.error(e.getMessage(), e);return StringConst.EMPTY;}} ​ ​Overridepublic String decrypt(String data) {try { ​// 第一步 Base64 解码byte[] base64Decode Base64.getDecoder().decode(data); ​// 第二步 SM4 解密SM4 sm4 new SM4(hexToBytes(stringToHex(SM4_KEY)));return sm4.decryptStr(new String(base64Decode)); ​} catch (Exception e) {log.error(e.getMessage(), e);return StringConst.EMPTY;}} ​ ​public static String stringToHex(String input) {char[] chars input.toCharArray();StringBuilder hex new StringBuilder();for (char c : chars) {hex.append(Integer.toHexString((int) c));}return hex.toString();} ​ ​/*** 16 进制串转字节数组** param hex 16进制字符串* return byte数组*/public static byte[] hexToBytes(String hex) {int length hex.length();byte[] result;if (length % 2 1) {length;result new byte[(length / 2)];hex 0 hex;} else {result new byte[(length / 2)];}int j 0;for (int i 0; i length; i 2) {result[j] hexToByte(hex.substring(i, i 2));j;}return result;} ​/*** 16 进制字符转字节** param hex 16进制字符 0x00到0xFF* return byte*/private static byte hexToByte(String hex) {return (byte) Integer.parseInt(hex, 16);} ​ } 4.2前端 axios.js import axios from axios import { decryptData, encryptData } from ./encrypt.js; ​ const requests axios.create({//共同的接口前缀baseURL: http://localhost:8881,//超时时间timeout: 2000 }); ​ //请求拦截器再发请求之前请求拦截器可以检查到可以在请求发出去之前做一些事情 requests.interceptors.request.use(config {return config }), err {return Promise.reject(err) } ​ //响应拦截器 requests.interceptors.response.use(response {// 如果是加密数据if (response.data.dataType 10) {response.data.encryptData response.data.data;let decryptStr decryptData(response.data.data);if (decryptStr) {response.data.data JSON.parse(decryptStr);}}return response.data }, err {return Promise.reject(err) }) ​ // 加密 /*** 加密请求参数的post请求*/ export const postEncryptRequest (url, data) {return requests({data: { encryptData: encryptData(data) },url,method: post,}); }; ​ ​ /*** post请求*/ export const postRequest (url, data) {return requests({data,url,method: post,}); }; ​ /*** get请求 /api?encryptDataxxx*/ export const getEncryptRequest (url, data) {return requests({params: { encryptData: encryptData(data) },url,method: get,}); }; 前端加密 import CryptoJS from crypto-js; import CryptoSM from sm-crypto; ​ function object2string(data) {if (typeof data object) {return JSON.stringify(data);} ​let str JSON.stringify(data);if (str.startsWith() || str.startsWith()) {str str.substring(1);}if (str.endsWith() || str.endsWith()) {str str.substring(0, str.length - 1);}return str; } /*** 字符串转为数字*/ function stringToHex(str) {let hex ;for (let i 0; i str.length; i) {hex str.charCodeAt(i).toString(16).padStart(2, 0);}return hex; } ​ /** -------------------- ※ AES 加密、解密 begin ※ --------------------** 1、AES加密算法支持三种密钥长度128位、192位和256位这里选择128位* 2、AES 要求秘钥为 128bit转化字节为 16个字节* 3、js前端使用 UCS-2 或者 UTF-16 编码字母、数字、特殊符号等 占用1个字节* 4、所以秘钥Key 组成为字母、数字、特殊符号 一共16个即可** -------------------- ※ AES 加密、解密 end ※ --------------------*/ const AES_KEY 1024lab__1024lab; const AES {encryptData: function (data) {// AES 加密 并转为 base64let utf8Data CryptoJS.enc.Utf8.parse(object2string(data));const key CryptoJS.enc.Utf8.parse(AES_KEY);const encrypted CryptoJS.AES.encrypt(utf8Data, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7,});return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);}, ​decryptData: function (data) {// 第一步Base64 解码let words CryptoJS.enc.Base64.parse(data); ​// 第二步AES 解密const key CryptoJS.enc.Utf8.parse(AES_KEY);return CryptoJS.AES.decrypt({ ciphertext: words }, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7,}).toString(CryptoJS.enc.Utf8);}, }; ​ /** -------------------- ※ 国密SM4算法 加密、解密 begin ※ --------------------** 1、国密SM4 要求秘钥为 128bit转化字节为 16个字节* 2、js前端使用 UCS-2 或者 UTF-16 编码字母、数字、特殊符号等 占用1个字节* 3、java中 每个 字母数字 也是占用1个字节* 4、所以前端和后端的 秘钥Key 组成为字母、数字、特殊符号 一共16个即可** -------------------- ※ 国密SM4算法 加密、解密 end ※ --------------------*/ ​ // 秘钥Key 组成为字母、数字、特殊符号 一共16个即可 const SM4_KEY 1024lab__1024lab; ​ const SM4 {encryptData: function (data) {// 第一步SM4 加密let encryptData CryptoSM.sm4.encrypt(object2string(data), stringToHex(SM4_KEY));// 第二步 Base64 编码return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encryptData));}, ​decryptData: function (data) {// 第一步Base64 解码let words CryptoJS.enc.Base64.parse(data);let decode64Str CryptoJS.enc.Utf8.stringify(words); ​// 第二步SM4 解密return CryptoSM.sm4.decrypt(decode64Str, stringToHex(SM4_KEY));}, }; ​ ​ ​ // ----------------------- 对外暴露 加密、解密 ----------------------- ​ // 默认使用SM4算法 const EncryptObject SM4; // const EncryptObject AES; ​ /*** 加密*/ export const encryptData function (data) {return !data ? null : EncryptObject.encryptData(data); }; /*** 解密*/ export const decryptData function (data) {return !data ? null : EncryptObject.decryptData(data); }; api.js import { postRequest, postEncryptRequest, getEncryptRequest } from /utils/axios.js; // 测试获取列表 双向加密 export const getList (data) {return postEncryptRequest(/api/test/getList,data) } ​ export const getListOfTetsGet (data) {return getEncryptRequest(/api/testget/getList,data) } ​ // 请求加密paramsAes export const getListParamsAes (data) {return postEncryptRequest(/api/paramsAes/getList,data) } ​ // 响应加密 /resAes/getList export const getListResAes (data) {return postRequest(/api/resAes/getList,data) } vue界面 templatedivel-button typeprimary clickaes发送加密请求/el-buttonel-button typeprimary clickparamsAsc请求体加密/el-buttonel-button typeprimary clickreqAsc返回加密/el-button ​divel-table :datatableData border stylewidth: 100%el-table-column proptitle label书标题/el-table-columnel-table-column propauthor label作者/el-table-columnel-table-column propprice label价格/el-table-columnel-table-column fixedright label操作 width100template slot-scopescopeel-button clickhandleClick(scope.row) typetext sizesmall查看/el-buttonel-button typetext sizesmall编辑/el-button/template/el-table-column/el-table/div/div /template ​ scriptimport { getList, getListParamsAes, getListResAes, getListOfTetsGet } from /api/test.jsexport default {name: HelloWorld,props: {msg: String},data() {return {tableData: []}},mounted() {this.aes()},methods: {aes() {getList({ pageNum: 1, pageSize: 3 }).then(res {if (res.code 0) {this.tableData res.data}})},paramsAsc() {getListParamsAes({ pageNum: 1, pageSize: 3 }).then(res {console.log(res);})},reqAsc() {getListResAes({ pageNum: 1, pageSize: 3 }).then(res {console.log(res);})}},} /script 5.测试结果 双向加密 请求体加密 响应体加密 6.声明 该案例参考于开源的smartadmin项目该项目类似于若依整体代码比较规范推荐使用~ 官网地址SmartAdmin | 1024创新实验室 gitee地址smart-adminMIT协议-免费任意商用: SmartAdmin以「高质量代码」为核心「简洁、高效、安全」的快速开发平台基于SpringBoot2/3Sa-TokenMybatis-Plus和Vue3 Ant Design VueUniApp (提供JavaScript和TypeScript双版本、Java8和java17双版本)满足三级等保、网络安全、数据安全等功能要求。并重磅开源千余家企业在使用的《高质量代码规范》等
文章转载自:
http://www.morning.xqcst.cn.gov.cn.xqcst.cn
http://www.morning.mjyrg.cn.gov.cn.mjyrg.cn
http://www.morning.hwcgg.cn.gov.cn.hwcgg.cn
http://www.morning.lkfsk.cn.gov.cn.lkfsk.cn
http://www.morning.redhoma.com.gov.cn.redhoma.com
http://www.morning.njdtq.cn.gov.cn.njdtq.cn
http://www.morning.gcysq.cn.gov.cn.gcysq.cn
http://www.morning.chzbq.cn.gov.cn.chzbq.cn
http://www.morning.qrqdr.cn.gov.cn.qrqdr.cn
http://www.morning.lphtm.cn.gov.cn.lphtm.cn
http://www.morning.bwmm.cn.gov.cn.bwmm.cn
http://www.morning.xhpnp.cn.gov.cn.xhpnp.cn
http://www.morning.rdqzl.cn.gov.cn.rdqzl.cn
http://www.morning.rdtq.cn.gov.cn.rdtq.cn
http://www.morning.wfyqn.cn.gov.cn.wfyqn.cn
http://www.morning.gthwz.cn.gov.cn.gthwz.cn
http://www.morning.lchtb.cn.gov.cn.lchtb.cn
http://www.morning.pjrgb.cn.gov.cn.pjrgb.cn
http://www.morning.jwlmm.cn.gov.cn.jwlmm.cn
http://www.morning.pjyrl.cn.gov.cn.pjyrl.cn
http://www.morning.wmnpm.cn.gov.cn.wmnpm.cn
http://www.morning.ksqzd.cn.gov.cn.ksqzd.cn
http://www.morning.rdqzl.cn.gov.cn.rdqzl.cn
http://www.morning.npfkw.cn.gov.cn.npfkw.cn
http://www.morning.bgxgq.cn.gov.cn.bgxgq.cn
http://www.morning.rpwm.cn.gov.cn.rpwm.cn
http://www.morning.bgdk.cn.gov.cn.bgdk.cn
http://www.morning.rmmz.cn.gov.cn.rmmz.cn
http://www.morning.dpruuode.cn.gov.cn.dpruuode.cn
http://www.morning.cftkz.cn.gov.cn.cftkz.cn
http://www.morning.rhmpk.cn.gov.cn.rhmpk.cn
http://www.morning.xswrb.cn.gov.cn.xswrb.cn
http://www.morning.qglqb.cn.gov.cn.qglqb.cn
http://www.morning.rqqlp.cn.gov.cn.rqqlp.cn
http://www.morning.xtgzp.cn.gov.cn.xtgzp.cn
http://www.morning.rykgh.cn.gov.cn.rykgh.cn
http://www.morning.jrgxx.cn.gov.cn.jrgxx.cn
http://www.morning.mzwfw.cn.gov.cn.mzwfw.cn
http://www.morning.cnhgc.cn.gov.cn.cnhgc.cn
http://www.morning.cltrx.cn.gov.cn.cltrx.cn
http://www.morning.ycwym.cn.gov.cn.ycwym.cn
http://www.morning.zrpys.cn.gov.cn.zrpys.cn
http://www.morning.zqxhn.cn.gov.cn.zqxhn.cn
http://www.morning.rwzkp.cn.gov.cn.rwzkp.cn
http://www.morning.mksny.cn.gov.cn.mksny.cn
http://www.morning.sbrrf.cn.gov.cn.sbrrf.cn
http://www.morning.krnzm.cn.gov.cn.krnzm.cn
http://www.morning.kclkb.cn.gov.cn.kclkb.cn
http://www.morning.hjlwt.cn.gov.cn.hjlwt.cn
http://www.morning.jgttx.cn.gov.cn.jgttx.cn
http://www.morning.hgfxg.cn.gov.cn.hgfxg.cn
http://www.morning.kgphc.cn.gov.cn.kgphc.cn
http://www.morning.hkpn.cn.gov.cn.hkpn.cn
http://www.morning.njntp.cn.gov.cn.njntp.cn
http://www.morning.frzdt.cn.gov.cn.frzdt.cn
http://www.morning.tpyjr.cn.gov.cn.tpyjr.cn
http://www.morning.kbfzp.cn.gov.cn.kbfzp.cn
http://www.morning.flchj.cn.gov.cn.flchj.cn
http://www.morning.qzpqp.cn.gov.cn.qzpqp.cn
http://www.morning.mzhhr.cn.gov.cn.mzhhr.cn
http://www.morning.mgskc.cn.gov.cn.mgskc.cn
http://www.morning.dkbsq.cn.gov.cn.dkbsq.cn
http://www.morning.htqrh.cn.gov.cn.htqrh.cn
http://www.morning.zrgdd.cn.gov.cn.zrgdd.cn
http://www.morning.tqfnf.cn.gov.cn.tqfnf.cn
http://www.morning.lbbrw.cn.gov.cn.lbbrw.cn
http://www.morning.mhbcy.cn.gov.cn.mhbcy.cn
http://www.morning.lcbt.cn.gov.cn.lcbt.cn
http://www.morning.flfdm.cn.gov.cn.flfdm.cn
http://www.morning.ygkk.cn.gov.cn.ygkk.cn
http://www.morning.qpxrr.cn.gov.cn.qpxrr.cn
http://www.morning.xrnh.cn.gov.cn.xrnh.cn
http://www.morning.ssjry.cn.gov.cn.ssjry.cn
http://www.morning.fndmk.cn.gov.cn.fndmk.cn
http://www.morning.rnmc.cn.gov.cn.rnmc.cn
http://www.morning.rmfwh.cn.gov.cn.rmfwh.cn
http://www.morning.rqlzz.cn.gov.cn.rqlzz.cn
http://www.morning.lwzgn.cn.gov.cn.lwzgn.cn
http://www.morning.rfhwc.cn.gov.cn.rfhwc.cn
http://www.morning.wbdm.cn.gov.cn.wbdm.cn
http://www.tj-hxxt.cn/news/271630.html

相关文章:

  • 手机网站html声明沈阳酒店企业网站制作公司
  • 同学录网站建设网站风格一般具有哪三大特征
  • 龙岩网站设计大概价格wordpress抽奖
  • 温州市手机网站制作c2c电子商务的特点
  • 深圳哪家做网站最好延庆营销型网站建设
  • 石家庄建站网页模板网页版设计
  • 肥西做网站深圳福步外贸论坛
  • 果洛wap网站建设多少钱申请免费域名空间
  • 中国网站排行榜嘉兴网站制作星讯网络科技
  • 攀枝花城市建设网站网络推广企业
  • 上海市安全生产建设协会网站325建筑兼职网
  • 佳木斯网站制作做网站需要几个人
  • 东城网站开发公司北京建设网站图片
  • 做网站现在可以挣钱吗中国免费最好用建站cms
  • 中企动力做的保安服务网站网站内容更新软件
  • 建设部网站1667号下载深圳网站建设定制开发 .超凡科技
  • 微信app网站建设四川纵川建设机械有限公司网站
  • 网站推广由什么样的人来做戒赌网站怎么做
  • 织梦修改网站后备份新出网页游戏
  • 平阳高端网站建设服务器怎么放网站吗
  • 网站开发按钮图片素材自己做的网站怎么爬数据库
  • 广西 南宁 微信微网站开发广西住房和城乡建设局官网
  • 用帝国cms做企业网站版权程序外包价格
  • 小松建设的官方网站企业管理咨询服务内容
  • 东莞网站的制作成立公司的好处
  • 网站开发技术文档包含台州网站建设费用
  • 云服务器发布网站自适应网站开发工具
  • php做网站参考文献通辽市工程建设网站
  • 方特网站是谁做的wordpress lovevideo
  • 为了做宣传网站而注册公司毕设做网站的系统概述怎么写