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

Web开发中前端与Node服务中的信息安全与解决办法

Web开发中前端与Node服务中的信息安全与解决办法input限制特殊字符和长度漏洞描述 永远不要相信用户输入的信息如常规的注入脚本通过input输入之后被页面执行整改办法方法1对于vue项目中ElementUI的el-input 和 原生inputel-input :placeholderprivateSearchPlaceholder v-model.trimprivateValue keyup.enter.nativequerySearchStr clearable maxlength100 clearclearSearchStr/el-input watch: {/** * 监听文本框值变化 * */privateValue (val) {// 此处不加nextTick显示的还会使原来的带有特殊字符的字符串但是实际的值已经改变this.$nextTick(() {// 去除特殊字符(除去数字字母中文之外都是特殊字符)this.privateValue val.replace(/[^a-zA-Z0-9/u4e00-/u9fa5]/g, ) // this.privateValue this.$myTools.stringFilter(val) // 也可全局注册过滤函数})} }方法2针对ElementUI的el-inputel-input inputonInput v-model.trimsearchStr/el-input methods:{onInput(val){console.log(val)this.searchStr e.replace(/[^a-zA-Z0-9/u4e00-/u9fa5]/g, )} }注意前端禁止了特殊字符但是抓包工具直接请求还是可以发送特殊字符所以建议后端关键接口也要对特殊字符做处理SQL注入也可用类似方法解决部分当然如果已经做了防重放的话也可以理论上避免抓包重发。密码强度要求漏洞描述涉及到用户密码的系统需要限制用户对账号密码的复杂度做要求不可允许使用弱密码整改建议配置安全合理的密码策略如必须为包含数字、字母、特殊字符且长度不可短于8位,下面是对复杂度做验证的函数密码长度8~30位且必须包含字母、数字、特殊字符的vue表单校验 let pwd ; var pwdValidate function(rule, value, callback){pwd valueif(!value){return callback(new Error(密码不可为空))}else{// 正则表达式校验密码if (value.length 8 value.length 30 value.replace(/[a-zA-Z0-9]/g, ).length 0) {if (_userAccount (value.includes(_userAccount) || value _userAccount)) {return callback(new Error(密码中不允许出现用户名或与用户名相同))}callback()}else {return callback(new Error(密码长度8~30位且必须包含字母、数字、特殊字符));}} }敏感数据加密漏洞描述用户登录帐号与密码、用户姓名、身份证、电话等关键信息不可明文传输整改方式采用加密处理切记不可只采用单层md5加密虽然md5不可解密但是现在采用字典暴力破解的可能性也越来越大1可以在加密时加入salt减小被碰撞破解的可能或者采用对称或者非对称加密2对称加密加密与解密使用的是同样的密钥速度快但由于需要将密钥在网络传输所以安全性不高。3 非对称加密使用了一对密钥公钥与私钥所以安全性高但加密与解密速度慢。4 适当的解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密然后发送出去接收方使用私钥进行解密得到对称加密的密钥然后双方可以使用对称加密来进行沟通。不安全的http请求方式现象描述 在信息安全测试的项中竟然要求禁止除GET和POST之外的HTTP方法开始不是很理解查询之后说法如下为什么要禁止除GET和POST之外的HTTP方法一、HTTP请求方法有哪些HTTP1.0定义了三种请求方法 GET、POST、HEADHTTP1.1新增了五种请求方法OPTIONS、PUT、DELETE、TRACE 、CONNECT二、举例说明不安全的HTTP方法GET、POST是最为常见方法而且大部分主流网站只支持这两种方法因为它们已能满足功能需求。其中GET方法主要用来获取服务器上的资源而POST方法是用来向服务器特定URL的资源提交数据。而其它方法出于安全考虑被禁用所以在实际应用中九成以上的服务器都不会响应其它方法并抛出404或405错误提示。以下列举几个HTTP方法的不安全性1、OPTIONS方法将会造成服务器信息暴露如中间件版本、支持的HTTP方法等。2、PUT方法由于PUT方法自身不带验证机制利用PUT方法即可快捷简单地入侵服务器上传Webshell或其他恶意文件从而获取敏感数据或服务器权限。3、DELETE方法利用DELETE方法可以删除服务器上特定的资源文件造成恶意攻击。建议把除了GET、POST的HTTP方法禁止有两方面原因1、除GET、POST之外的其它HTTP方法其刚性应用场景较少且禁止它们的方法简单即实施成本低2、一旦让低权限用户可以访问这些方法他们就能够以此向服务器实施有效攻击即威胁影响大。整改建议配置仅支持GETPOST方法即可文件上传安全验证关于涉及到上传文件的接口一定要严格校验包括格式文件内容文件名进行严格校验CSRF 跨站请求伪造——请求伪造特点用户必须登录原理利用网站漏洞去自动执行一些接口举例防御措施1.Token 验证2.请求头中Referer验证页面来源判断3.隐藏令牌 在http头或者请求中添加隐藏的口令其中一个是对 referer 的校验通用做法也就是只允许我们制定的域名发送的请求其他站点则认为是非法请求比如下面我们的中间件只要存在 referer并且 referer 不在我们的域名白名单下那么则直接返回 403 拒绝访问。const baseFun require(../lib/baseFun); const whiteList [127.0.0.1:3000 ]; module.exports function () {return async function ( ctx, next ) { if(ctx.request.headers.referer !whiteList.includes(ctx.request.headers.referer)){baseFun.setResInfo(ctx, false, access have been forbidden, null, 403);return; } return await next();} }另外一个是后台服务在写操作时使用 token 校验方式这里我们应用的是 JWT也就是在用户打开页面时将 token 写入页面的隐藏元素或者隐藏域中当请求接口时从页面元素中获取 token再传递到接口参数中这样第三方站点因为没有打开页面是无法获取到这个 token 的。表单等隐藏域案例如下input nameauthenticity_token typehidden valuelr/g5G/gLUzIhYpJwdtULW5afvcf8soZObMznkvxT0 /CSRF 攻击之所以能够成功是因为黑客可以完全伪造用户的请求该请求中所有的用户验证信息都是存在于 cookie 中因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF关键在于在请求中放入黑客所不能伪造的信息并且该信息不存在于 cookie 之中。可以在 HTTP 请求头中以参数的形式加入 token并在服务器端建立一个拦截器来验证这个 token如果请求中没有 token 或者 token 内容不正确则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查 Referer 要安全一些token 可以在用户登陆后产生并放于 session 之中然后在每次请求时把 token 从 session 中拿出与请求中的 token 进行比对身份凭证信息泄露漏洞描述身份凭证信息token不可直接在url中显示最好也不要存放在cookie中以防止直接复制进行伪操作整改建议避免在url中直接传输用户凭证信息等重要敏感信息数据Tips: 如果数据存储在Cookies中那么只要是服务是同域的也可以通过nginx实现多个服务的同域cookies也是可以共享的会话终止机制漏洞描述登录后会话长时间无操作不会自动注销但是此处如果正常操作下token过期如何重新获取token保证用户的正常使用有的策略会在用户持续访问后台接口的时候更新token的过期时间但是单纯的修改token的过期时间会被攻击利用从而一致不失效这样是不安全的。失效之后的处理策略一般会做两种处理​ 一种是直接跳转到登录页面重新登录​ 第二种是如果返回 token失效的信息自动去刷新token然后继续完成未完成的请求操作。第一种不需要解释针对第二种此时我们要考虑一个问题通常一个页面中不只是发送一个异步请求可能会同时发送多个异步请求并且多个请求都需要验证token如果一个过期了需要刷新token那其他请求在那一瞬间之后都会过期除了第一次判断token失效后进行刷新token的操作其余的刷新token都是多余的。伪代码实现如下const axios require(axios); // 封装请求 function request(url, options) {const token localStorage.getItem(token);const defaultOptions {headers: {Authorization: Bearer ${token},},withCredentials: true,url: url,baseURL: BASE_URL,};const newOptions { ...options, ...defaultOptions };return axios.request(newOptions).then(checkStatus).catch(error console.log(error)); } // 默认刷新标识位 let isRefreshing true; function checkStatus(response) {if (response response.code 401) {// 刷新token的函数,这需要添加一个开关防止重复请求if(isRefreshing){refreshTokenRequst()}isRefreshing false;// 将当前的请求保存在观察者数组中const retryOriginalRequest new Promise((resolve) {addSubscriber(() {resolve(request(url, options))})});return retryOriginalRequest;}else{return response;} } function refreshTokenRequst(){let data;const refreshToken localStorage.getItem(refreshToken);data{authorization: YXBwYXBpczpaSWxhQUVJdsferTeweERmR1praHk,refreshToken,}axios.request({baseURL: BASE_URL,url:/classList,method: POST,data,}).then((response){// 刷新完成后,将刷新token和refreshToken存储到本地localStorage.setItem(refreshToken,response.data.refreshToken);localStorage.setItem(token,response.data.token);// 并且将所有存储到观察者数组中的请求重新执行。onAccessTokenFetched();// 刷新标识位撕掉isRefreshing true;}); } // 观察者 let subscribers []; function onAccessTokenFetched() {subscribers.forEach((callback){callback();})subscribers []; } function addSubscriber(callback) {subscribers.push(callback) }可以看到刷新标识位相当于变量isRefreshing观察者相当于数组subscribers。以上便是token失效时的处理策略是否需要单点登录漏洞描述如果不是单点登录则同一账号可多处进行登录即浏览器A登录系统再使用浏览器B使用同一账号登录系统A浏览器会话未被关闭。整改建议如果系统具有单点登录需求则需要在下一个地点登录通过后终止上一个地点的会话XSS (cross site script)跨域脚本攻击——脚本注入特点用户无需登录攻击原理向页面注入js脚本运行XSS举例· 新浪博客写一篇文章同时偷偷插入一段· 攻击代码中获取 cookie发送自己的服务器· 发布博客有人查看博客内容· 会把查看者的cookie发送到攻击者的服务器防御措施前端将脚本关键代码如///*后端替换也可//一个开箱即用的Vue.js插件可通过简单的方式防止XSS攻击 github.com/hua909000/v… ////npm install vue-xss --savemain.jsimport VueXss from “vue-xss”;Vue.use(VueXss);xxx.vue中**对于服务端接口而言尽量不要直接吐出数据而是统一经过处理层进行转化。**class Xss extends Controller {index() {const params querystring.parse(this.ctx.request.querystring);let name decodeURI(params[‘name’]);return this.ctx.response.body name;//return this.resApi(true, ‘good’, a);}}module.exports Xss;没有对 name 进行任何处理就直接返回给接口并且没有经过我们的 resApi 服务而是使用 body 直接设置返回/**。这样就会导致/**当 name 为一个 HTML 或者 JS 都会被浏览器执行/**。当我们启动服务后访问以下地址都会出现一些异常问题。* /*http://127.0.0.1:3000/v1/xss/index?name%3Cscript%3Ealert(%27nodejs%27)%3C/script%3E http://127.0.0.1:3000/v1/xss/index?name%3Chtml%3E%3Ch1%3E%E6%88%91%E6%83%B3%E6%89%93%E5%8D%B0%E4%BB%80%E4%B9%88%EF%BC%8C%E5%B0%B1%E6%89%93%E5%8D%B0%E4%BB%80%E4%B9%88%EF%BC%8C%E4%BD%A0%E7%BD%91%E7%AB%99%E8%A2%AB%E6%94%BB%E5%87%BB%E4%BA%86%3C/h1%3E%3C/html%3E 这里最简单的防御方式就是使用我们统一的 resApi 处理响应数据因为在 resApi 中固定了返回结果进行了 JSON.stringify 处理所有的返回都会封装为一个 json 字符串因此不会存在 XSS 的问题。 /*/* **也可参考下文** **xss前后端预防方法**[juejin.cn/post/684490…](https://juejin.cn/post/6844903685122703367#heading-14 https://juejin.cn/post/6844903685122703367#heading-14) **Web安全系列四XSS 的防御****[juejin.cn/post/684490…](https://juejin.cn/post/6844903684900388871 https://juejin.cn/post/6844903684900388871)** nodejs服务端渲染的时候可以使用js-xss包进行处理 [jsxss.com/zh/starter/…](https://link.juejin.cn/?targethttps%3A%2F%2Fjsxss.com%2Fzh%2Fstarter%2Fquickstart.html https://jsxss.com/zh/starter/quickstart.html) 接口防重放 ----- ### 概念 重放攻击Replay Attacks是指攻击者发送一个目的主机已接收过的包来达到欺骗系统的目的主要用于身份认证过程破坏认证的正确性。 它是一种攻击类型这种攻击会不断恶意或欺诈性地重复一个有效的数据传输重放攻击可以由发起者也可以由拦截并重发该数据的敌方进行。攻击者利用网络监听或者其他方式盗取认证凭据之后再把它重新发给认证服务器。 加密可以有效防止会话劫持但是却防止不了重放攻击。 ### 防御手段 **1.时间戳** A接收一个消息当且仅当其包含一个对A而言足够接近当前时刻的时间戳而被重放的时戳将相对远离当前时刻 但是这必须要求通信各方的计算机时钟保持同步设置大小适当的时间窗间隔越大越能包容网络传输延时越小越能防重放攻击。 但是这样有个缺点就是在连接情形下双方时钟若偶然出现不同步则正确的信息可能会被误判为重放信息而丢弃而错误的重放信息可能会当作最新信息而接收 **2.序号** 通信双方通过消息中的序列号来判断消息的新鲜性 要求通信双方必须事先协商一个初始序列号并协商递增方法 **3.提问与应答** “现时”──与当前事件有关的一次性随机数N互不重复即可 基本做法──期望从B获得消息的A 事先发给B一个现时N并要求B应答的消息中包含N或f(N)f是A、B预先约定的简单函数 原理──A通过B回复的N或f(N)与自己发出是否一致来判定本次消息是不是重放的 以登陆为例看具体的例子 ----------- **常规流程** 1.前端web页面用户输入账号、密码点击登录。 2.请求提交之前web端首先通过客户端脚本如javascript对密码原文进行md5加密。 3.提交账号、md5之后的密码 4.请求提交至后端验证账号与密码是否与数据库中的一致一致则认为登录成功反之失败。 **有什么问题呢** 上述流程看似安全认为传输过程中的密码是md5之后的即使被监听截取到由于md5的不可逆性密码明文也不会泄露。 其实不然监听者无需解密出密码明文即可登录监听者只需将监听到的url如http:///*/*/*/*/login.do?methodloginpasswordmd5之后的密码userid登录账号重放一下即可冒充你的身份登录系统。 **稍微安全点的方式** 1.进入登陆页面时生成一个随机码称之为盐值在客户端页面和session中各保存一份。 2.客户端提交登录请求时将md5之后的密码与该随机码拼接后再次执行md5然后提交提交的密码md5(md5(密码明文)随机码)。 3.后端接收到登录请求后将从数据库中查询出的密码与session中的随机码拼接后md5运算然后与前端传递的结果进行比较。 **为何要这样** 该登录方式即使登录请求被监听到回放登录URL由于随机码不匹配监听者的session中的随机码与被监听者的session中的随机码相同概率可忽略无法登录成功。 该登录方式由于传输的密码是原密码md5之后与随机码再次md5之后的结果即使监听者采用暴力破解的方式也很难解密出密码明文。 简单密码的md5结果很容易通过暴力破解的方式给解密出来何况md5出现了这么多年可能已经有不少字典了同时为了方便用户登录的方便性我们的系统一般不可能要求用户设置很长、很复杂的密码怎么办加**固定盐值**。 1.系统设置一个固定的盐值该盐值最好足够复杂如:1qaz2wsx3edc4rfv!#$%^qqtrtRTWDFHAJBFHAGFUAHKJFHAJHFJHAJWRFA 2.用户注册、修改密码时将用户的原始密码与我们的固定盐值拼接然后做md5运算。 3.传递至后端保存进数据库数据库中保存的密码是用户的原始密码拼接固定盐值后md5运算后的结果。 4.登录时将用户的原始密码与我们的固定盐值进行拼接然后做md5运算运算后的结果再拼接上我们的随机码再次md5运算然后提交。 5.后端接收到登录请求后将从数据库中查询出的密码与session中的随机码拼接后md5运算然后与前端传递的结果进行比较。 **再进一步** 1.加登录验证码可预防人为地暴力登录破解 2.账户锁定如果用户密码输入错误次数达到一定量后如6次则可以锁定该账号 ### 使用时间戳随机数作为防重放方式的实际代码 前端const crypto require(‘crypto’);const md5 require(‘md5’);// 加密秘钥var AES_conf {key: “ESS-2019$05#sb%_”, //密钥iv: ‘1012132405963708’ //偏移向量}export default{/** * AES_128_CBC 加密 * 128位 * return base64/encryption:(data) {let key AES_conf.key;let iv AES_conf.iv;var cipherChunks [];var cipher crypto.createCipheriv(‘aes-128-cbc’, key, iv);cipher.setAutoPadding(true);cipherChunks.push(cipher.update(data, ‘utf8’, ‘base64’));cipherChunks.push(cipher.final(‘base64’));return cipherChunks.join(‘’);},/* * 解密 * return utf8/decryption:(data) {let key AES_conf.key;let iv AES_conf.iv; var cipherChunks [];var decipher crypto.createDecipheriv(‘aes-128-cbc’, key, iv);decipher.setAutoPadding(true);try {cipherChunks.push(decipher.update(data, ‘base64’, ‘utf8’));cipherChunks.push(decipher.final(‘utf8’));return{code: 200, data: cipherChunks.join(‘’)};} catch (error) {return{code: 400, data: ‘密文错误解密失败’};}},// 数据完整性MD5字段生成generateIntegrityVal(data){return md5(JSON.stringify(data))},// 数据完整性校验integrityChecke(data, integrityValue){return (md5(JSON.stringify(data)) integrityValue)},//生成一定范围内的随机数random(start, end) {return parseInt(start Math.random() * (end - start))},/* * description: 生成防重放数字签名 */generateSign() {let timestamp new Date().getTime(),nonce parseInt(this.random(0,100000000)),//建议加上用户uid组合生成signsign md5(timestamp nonce);let val {timestamp,nonce,sign}return JSON.stringify(val)}}axios拦截器// http request 拦截器axios.interceptors.request.use(request {// 防重放签名request.headers[‘sign’] tools.generateSign()return request;},err {});node expressjs服务端代码// CSRF验证referer头app.use(function (req, res, next) {let referer req.get(‘Referrer’) || req.headers.referer || req.headers.hostlogger.info(‘referer:’, referer)if (img src“http://‘)) {referer referer.substring(7)}if (referer.endsWith(’/)) {referer referer.substring(0, referer.length - 1)}console.log(‘endReferer’,referer)if (config._systemConf.safeReferers.includes(referer)) {next();} else {next({status: 403,message: “Your request was Forbidden!”})}” style“margin: auto” /});//防重放 map数组var signMap tools.signMap;//防重放函数app.use((req, res, next) {// 静态文件不做防重放if(req.path ‘/’ || tools.interceptFilter(req, [‘.jpg’, ‘.png’, ‘.ico’,‘.icon’, ‘.html’, ‘.jpeg’, ‘dist’, ‘.js’, ‘.css’])){next()}else{if(!req.headers.sign){next({status: 403,message: “Your request was Forbidden!!”})}else{//获取sign对象let signObj JSON.parse(req.headers.sign);//根据传入时间戳以及随机数生成signlet sign md5(signObj.timestamp signObj.nonce);logger.info(‘重放时间’,(new Date().getTime() - signObj.timestamp), config._systemConf.ReplayTime)//检验是否与前端生成的sign一致,判断请求时间间隔是否小于60s,判断此次sign不存在于signMap数组中if (signObj sign signObj.sign (new Date().getTime() - signObj.timestamp) config._systemConf.ReplayTime signMap.every(item item.sign ! sign)) {signMap.push(signObj);next()} else {next({status: 403,message: “Your request was Forbidden!!!”})}}}})tools.js/**Created by Administrator on 2017/6/21./“use strict”const crypto require(‘crypto’);const md5 require(‘md5’);// 加密秘钥要和前端一致var AES_conf {key: “ESS-2019$05#sb%_”, //密钥iv: ‘1012132405963708’ //偏移向量}module.exports {/* * AES_128_CBC 加密 * 128位 * return base64/encryption: (data) {let key AES_conf.key;let iv AES_conf.iv;var cipherChunks [];var cipher crypto.createCipheriv(‘aes-128-cbc’, key, iv);cipher.setAutoPadding(true);cipherChunks.push(cipher.update(data, ‘utf8’, ‘base64’));cipherChunks.push(cipher.final(‘base64’));return cipherChunks.join(‘’);// return cipherChunks.join(‘’).replace(new RegExp(‘’,‘g’),‘’)},/* * 解密 * return utf8/decryption: (data) {// let add data.length%3;// for(let i 0 ;iadd ;i){// data‘’// }let key AES_conf.key;let iv AES_conf.iv;var cipherChunks [];var decipher crypto.createDecipheriv(‘aes-128-cbc’, key, iv);decipher.setAutoPadding(true);try {cipherChunks.push(decipher.update(data, ‘base64’, ‘utf8’));cipherChunks.push(decipher.final(‘utf8’));return {code: 200,data: cipherChunks.join(‘’)};} catch (error) {return {code: 400,data: ‘密文错误解密失败’};}},// 数据完整性校验integrityChecke(data, integrityValue) {return (md5(JSON.stringify(data)) integrityValue)},/* * description: 生成一定范围内的随机数 * param {start} * param {end} * return:/random(start, end) {return parseInt(start Math.random() * (end - start))},/* * description: 防重放请求仓库(对象数组)/signMap: [],// 生成防重放数字签名generateSign() {let timestamp new Date().getTime(),nonce parseInt(this.random(0,100000000)),//建议加上用户uid组合生成signsign md5(timestamp nonce);return {timestamp,nonce,sign}},/* * * 拦截筛选函数 */interceptFilter(req, filterArr){let ifFilter false; // 初始全部拦截for(let filter of filterArr){if(req.path.includes(filter)){ifFilter true// 包含过滤器中的字段就不拦截}}return ifFilter}};接口数据完整性 ------- **用户登录和修改密码等关键接口需要做** 可以在请求头中增加完整性integrity字段或者像下面这样单独加一个参数用来存储tools.js // 数据完整性MD5字段生成generateIntegrityVal(data){return md5(JSON.stringify(data))},updatePassword: function (userID, oldPwd, newPwd, callback) { let _params { id: userID, oldPwd: tools.encryption(oldPwd), // 敏感数据加密 newPwd: tools.encryption(newPwd) } let integrityValue tools.generateIntegrityVal(_params)// 数据完整性MD5字段生成,后端做校验 axios.post(‘/uums/users/updatePassword’, { userId: _params.id, oldPwd: _params.oldPwd, newPwd: _params.newPwd, integrity: integrityValue }).then((res) { callback(res.data); });}SQL注入 ----- [www.zhihu.com/question/22…](https://link.juejin.cn/?targethttps%3A%2F%2Fwww.zhihu.com%2Fquestion%2F22953267%2Fanswer%2F80141632 https://www.zhihu.com/question/22953267/answer/80141632) **注入方式举例**原sql,${id} 为传入参数select * from tbl_topic_info wheretopic_id ${id}正常情况,传入的是正常的字符串 1select * from tbl_topic_info wheretopic_id ‘1’注入情况一传来的参数是 1’;SELECT pg_sleep(5)–select * from tbl_topic_info wheretopic_id ‘1’;SELECT pg_sleep(5)–’此时应为有分号导致查询变成了两条sqlsleep 也执行了注入情况二传来的参数是 1’ or 1 1 --;select * from tbl_topic_info wheretopic_id ‘1’ or 1 1 --;’这样就会获取到所有数据导致数据泄露但凡有SQL注入漏洞的程序都是因为程序要接受来自客户端用户输入的变量或URL传递的参数并且这个变量或参数是组成SQL语句的一部分对于用户输入的内容或传递的参数我们应该要时刻保持警惕这是**安全领域里的「外部数据不可信任」**的原则纵观Web安全领域的各种攻击方式大多数都是因为开发者违反了这个原则而导致的所以自然能想到的就是**从变量的检测、过滤、验证下手**确保变量是开发者所预想的。 永远不要信任来自用户端的变量输入有固定格式的变量一定要严格检查对应的格式没有固定格式的变量需要对引号等特殊字符进行必要的过滤转义。 1、检查变量数据类型和格式 2、过滤特殊符号 3、绑定变量使用预编译语句 在 Node.js 中有最常见的方法是**使用占位符(即预编译语句)的方式**也就是使用下面的方式替代拼装 SQL 语法的方法connection.query(‘SELECT * FROM student WHERE name ?’, [name], function(err, results) {})具体的**nodejs sequelize库防注入测试可查看下文:** [blog.csdn.net/bbhe/_work/a…](https://link.juejin.cn/?targethttps%3A%2F%2Fblog.csdn.net%2Fbbhe_work%2Farticle%2Fdetails%2F53229695 https://blog.csdn.net/bbhe_work/article/details/53229695)updateEliteStatusByTopicId: function (id, flag) {return sequelize.query(update tbl_topic_info set elitestatus $flag where topic_id $id,{type: sequelize.QueryTypes.UPDATE, // 指定sql为SELECTbind: {flag: flag,id: id,},}).then((result) {return result;}).catch((err) {logger.error(tools.getFileName(__filename) “::updateEliteStatusByTopicId::” err);throw err;});},// 多条件拼接getTopicByConSql: function (params) {let conSql “”;let conArr [];let bindObj {};if (params.topicTypeId) {conArr.push( type_id KaTeX parse error: Expected EOF, got } at position 57: …ms.topicTypeId;}̲if (params.sear…searchStr’ or topic_txt like ‘%$searchStr%’);bindObj.searchStr params.searchStr;}if (params.startDate) {conArr.push(create_time $startDate);bindObj.startDate params.startDate;}if (params.endDate) {conArr.push(create_time $endDate);bindObj.endDate params.endDate;}if (conArr.length 0) {for (let i in conArr) {if (i 0) {conSql where conArr[i];} else {conSql conSql and conArr[i];}}}return sequelize.query(//select * from tbl_topic_info wheretype_id $topicTypeId,select * from tbl_topic_info ${conSql} order by elitestatus desc, create_time desc,{type: sequelize.QueryTypes.SELECT, // 指定sql为SELECTbind: bindObj,}).then((result) {return result;}).catch((err) {logger.error(tools.getFileName(__filename) “::getTopicByConSql::” err);throw err;});},数据库信息加密安全 --------- 相信大家都还对2011年爆出的CSDN拖库事件记忆犹新这件事情导致CSDN处在风口浪尖被大家痛骂的原因就在于他们竟然明文存储用户的密码这引发了科技界对用户信息安全尤其是密码安全的强烈关注我们在防范SQL注入的发生的同时也应该未雨绸缪说不定下一个被拖库的就是你谁知道呢。 在Web开发中传统的加解密大致可以分为三种: 1、对称加密 即加密方和解密方都使用相同的加密算法和密钥这种方案的密钥的保存非常关键因为算法是公开的而密钥是保密的一旦密匙泄露黑客仍然可以轻易解密。常见的对称加密算法有AES、DES等。 2、非对称加密 即使用不同的密钥来进行加解密密钥被分为公钥和私钥用私钥加密的数据必须使用公钥来解密同样用公钥加密的数据必须用对应的私钥来解密常见的非对称加密算法有RSA等。 3、不可逆加密 利用哈希算法使数据加密之后无法解密回原数据这样的哈希算法常用的有md5、SHA-1等。 但是md5已经被通常的做法是为每个用户确定不同的密码加盐salt后再混合用户的真实密码进行md5加密 Dos --- **这种网络攻击的主要原理就是通过模拟无效的海量用户请求来导致后台服务的崩溃现象**。一般这种在后台服务中不需要考虑可以直接在网关层进行处理如果真的没有网关层的话可以考虑使用 NPM 中的一个[ddos 库](https://link.juejin.cn/?targethttps%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fddos%3FfileGuid%3DxxQTRXtVcqtHK6j8 https://www.npmjs.com/package/ddos?fileGuidxxQTRXtVcqtHK6j8)[www.npmjs.com/package/ddo…](https://link.juejin.cn/?targethttps%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fddos%3FfileGuid%3DxxQTRXtVcqtHK6j8 https://www.npmjs.com/package/ddos?fileGuidxxQTRXtVcqtHK6j8) 。 Node.js 中特有的一些问题 ---------------- #### eval 函数 **在任何情况下都应杜绝使用该函数因为该函数存在非常不可控的因素这点和 SQL 注入相似相当于 JS 代码注入**比如下面这段代码const querystring require(‘querystring’);const Controller require(‘…/…/core/controller’);class Eval extends Controller {index() {const params querystring.parse(this.ctx.request.querystring);// 获取参数 rlet r decodeURI(params[‘r’]);// 根据参数 r 动态调用 this._p() 获取执行结果let ret eval(this._q() ${r});return this.resApi(true, ‘good’, ret);}_q () {return 1;}_p () {return 2;}}module.exports Eval;代码比较简单假设我们希望用 eval 来动态调用内部的一些函数因此我们使用了 r 这个参数正常情况下是可以调用但是如果我们调用下面的地址http://127.0.0.1:3000/v1/eval/index?rthis._p();console.log(‘d’);const fsrequire(‘fs’);fs.readFileSync(__filename, ‘utf8’)访问后你会发现很恐怖的一幕源代码直接被返回了如图 1 所示。 ![图片](http://cdn.zhipoai.cn/8dd166fb.jpeg) 图 1 eval 泄漏源代码例子 因此**无论任何情况下代码中都不允许 eval 的使用因为不可控因素太大**。 #### 文件读写 在我们之前设计路由的时候有讲解过这个路径的问题就像下面这段代码// 去除非常规请求路径将-转化为大写pathname pathname.replace(‘…’, ‘’).replace(//-(/w)/g, (all,letter)letter.toUpperCase());第一个 replace 的两个点是非常重要的这样我们才能控制 require 的文件仅仅只在 controller 文件夹下。 接下来我们看一个没有控制好目录路径导致的问题比如下面这段代码class Fs extends Controller {index() {const params querystring.parse(this.ctx.request.querystring);// 根据产品名称获取产品的配置信息let product decodeURI(params[‘product’]);try {let productInfo fs.readFileSync(${__dirname}/../../config/products/${product}.json, ‘utf8’);return this.resApi(true, ‘good’, productInfo);} catch(err){return this.resApi(false, ‘can not find the product’);}}}正常访问以下两个链接都可以拿到我们具体需要的正常逻辑。http://127.0.0.1:3000/v1/fs/index?productchttp://127.0.0.1:3000/v1/fs/index?productd正常的返回结果如下{code: 200.msg: ‘’,data: “{name: ‘john’,age: 23}”}但是**如果我们访问了以下地址就直接导致了配置文件泄漏从而引发了数据库账号和密码被泄漏的安全问题**。http://127.0.0.1:3000/v1/fs/index?product…/b访问以后你就可以通过上面代码访问到我们项目中的所有配置文件了而配置文件中包含了非常多敏感信息{code: 200.msg: ‘’,data: “{database: ‘xxx’,user: ‘lilei’,pwd:‘xxx12334dd’}”}解决方案的话就是将访问的配置文件**控制在当前配置文件目录下**因此你需要将这种 … 路径进行替换比如使用下面代码修复后就解决了该问题。你再次启动服务访问上面路径后将会提示访问路径异常的信息。// 去掉上层目录访问product product.replace(‘…’, ‘’)但是这里要注意这样还是可以访问同目录下的文件的因此最好的方式是**将配置文件归类并且做好校验非范围内的配置文件不允许读取**。 其次在写文件时更加要注意风险问题一般情况下**分开写目录和源代码目录**例如可以将上传的文件或者日志文件放到另外一个单独目录并控制权限即可。**以防代码写漏洞导致本地文件被篡改或者写入一些脚本文件从而控制服务器**。 #### 非 root 用户权限 **在大部分情况下 Node.js 的进程是无须太多权限的只需要一些固定目录的读写权限因此我们只需要赋予 Node.js 服务最低的用户权限一定不要设置为 root 权限**。比如上面我们的 eval 函数导致的问题如果你是使用 root 权限那么就可以通过 Node.js fs 获取主机的登录密码从而直接控制这台机器。而在大部分公司主机和主机都是内网互通如果单台内网机器被攻克后就相当于整个公司的内网系统沦陷了。 为了解决这个问题**我们可以新建一个独立的用户然后创建 Node.js 所需要读写的日志以及其他目录权限赋予读写权限**如下所示adduser usernamechown -R /path**第一步创建用户第二步为用户归属权限**一般情况下只需要归属当前源代码路径和需要写日志的目录。 这部分内容来源于拉钩教育课程《Nodejs 应用开发实战》 [kaiwu.lagou.com/course/cour…](https://link.juejin.cn/?targethttps%3A%2F%2Fkaiwu.lagou.com%2Fcourse%2FcourseInfo.htm%3FcourseId%3D694%23%2Fdetail%2Fpc%3Fid%3D6795 https://kaiwu.lagou.com/course/courseInfo.htm?courseId694#/detail/pc?id6795) url地址混淆加密 --------- 在客户端产生请求时对接口url进行RSA加密处理。 假设我们本来需要访问 [api.example.com/articles](https://link.juejin.cn/?targethttp%3A%2F%2Fapi.example.com%2Farticles http://api.example.com/articles) 这样的一个接口接口返回json数据。在客户端访问之前我们先对这个url进行这样的处理 1.加客户端时间戳[api.example.com/1322470148/…](https://link.juejin.cn/?targethttp%3A%2F%2Fapi.example.com%2F1322470148%2Farticles http://api.example.com/1322470148/articles) 2.对url的path段进行rsa加密然后base64[api.example.com/TBhIskCgCN…](https://link.juejin.cn/?targethttp%3A%2F%2Fapi.example.com%2FTBhIskCgCN%2BWMK3PftbYzPQFAKvx9sE9OMOxvL00kCBlNiKw2C1Mb7oGcfUepTxauG06NLBNhr5BFtjt7Xu7uwdpUYyVcFRdI37SVyGRCOzaxACOGXGpX5dHZqQJia0icxwWJ%2BD1RiJqxFWQ%2B%2B3%2FIgUOgDzgvQnPIl420bpztB8%3D http://api.example.com/TBhIskCgCNWMK3PftbYzPQFAKvx9sE9OMOxvL00kCBlNiKw2C1Mb7oGcfUepTxauG06NLBNhr5BFtjt7Xu7uwdpUYyVcFRdI37SVyGRCOzaxACOGXGpX5dHZqQJia0icxwWJD1RiJqxFWQ3/IgUOgDzgvQnPIl420bpztB8) 我们真实访问的地址就变成了这样一个长长的 url 结构我们通过rsa算法的padding参数和时间戳就可以让这个后面长长的bas64串在每次访问的时候都发生变化同时我们可以在服务器端把一个小时之内的请求过的串都记下来并不让再次访问这样就防止了爬虫的重放请求尝试。 在服务器端我们就需要在做响应之前把url还原回来然后返回响应数据即可。 #### 如何入门网络安全 ##### 建议 多看书 阅读永远是最有效的方法尽管书籍并不一定是最好的入门方式但书籍的理解需要一定的基础但是就目前来看书籍是比较靠谱的入门资料。 现在Web安全书籍比较多因此大家在学习的过程中可以少走了不少的弯路。如果以上推荐书籍阅读有困难那就找自己能看得进的 Web 安全的书 当然纸上谈兵终觉浅最好还是实践一下。 对于那些没有学习方向和资料的同学可以看下我整理的资源这份资料经历过社会的实践可以说是当下全网较全的网络安全知识体系 ①网络安全学习路线 ②20份渗透测试电子书 ③安全攻防357页笔记 ④50份安全攻防面试指南 ⑤安全红队渗透工具包 ⑥网络安全必备书籍 ⑦100个漏洞实战案例 ⑧安全大厂内部视频资源 ⑨历年CTF夺旗赛题解析 # **《网络安全从零到精通全套学习大礼包》** #### 96节从入门到精通的全套视频教程免费领取 如果你也想通过学网络安全技术去帮助就业和转行我可以把我自己亲自录制的96节 从零基础到精通的视频教程以及配套学习资料无偿分享给你。 ![请添加图片描述](https://i-blog.csdnimg.cn/direct/88f12e9068e14b728b215f939a9ed28e.gif) #### 网络安全学习路线图 想要学习 网络安全作为新手一定要**先按照路线图学习****方向不对努力白费**。对于从来没有接触过网络安全的同学我帮大家准备了从零基础到精通学习成长路线图以及学习规划。可以说是最科学最系统的学习路线大家跟着这个路线图学习准没错。 ![请添加图片描述](https://i-blog.csdnimg.cn/direct/6d41d41d77204bfc9459b7a3d079371f.png) #### **配套实战项目/源码** 所有视频教程所涉及的实战项目和项目源码 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/4fd5acecbff8471098d6b027b62f45d5.png#pic_center) #### **学习电子书籍** 学习网络安全必看的书籍和文章的PDF市面上网络安全书籍确实太多了这些是我精选出来的 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/5458f21c6efa4e739621ffb5d4309b20.jpeg#pic_center) #### 面试真题/经验 ![请添加图片描述](https://i-blog.csdnimg.cn/direct/92a6ab8e26034045b97ae8ac36b2a650.png) #### 以上资料如何领取 **** ![img](https://i-blog.csdnimg.cn/img_convert/2a690cdb788e4b8698c94a5e32fdbeb7.jpeg) ###### .cn/direct/4fd5acecbff8471098d6b027b62f45d5.png#pic_center) #### **学习电子书籍** 学习网络安全必看的书籍和文章的PDF市面上网络安全书籍确实太多了这些是我精选出来的 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/5458f21c6efa4e739621ffb5d4309b20.jpeg#pic_center) #### 面试真题/经验 ![请添加图片描述](https://i-blog.csdnimg.cn/direct/92a6ab8e26034045b97ae8ac36b2a650.png) #### 以上资料如何领取 **** ![img](https://i-blog.csdnimg.cn/img_convert/2a690cdb788e4b8698c94a5e32fdbeb7.jpeg) ###### 文章来自网上侵权请联系博主

相关文章:

Web开发中前端与Node服务中的信息安全与解决办法

Web开发中前端与Node服务中的信息安全与解决办法 input限制特殊字符和长度 漏洞描述&#xff1a; 永远不要相信用户输入的信息&#xff0c;如常规的注入脚本通过input输入之后被页面执行 整改办法 方法1&#xff1a;对于vue项目中ElementUI的el-input 和 原生input <el-in…...

OpenClaw怎么部署?2026年3月OpenClaw(Clawdbot)在阿里云一键部署超全教程

OpenClaw怎么部署&#xff1f;2026年3月OpenClaw&#xff08;Clawdbot&#xff09;在阿里云一键部署超全教程。本文面向零基础用户&#xff0c;完整说明在轻量服务器与本地Windows11、macOS、Linux系统中部署OpenClaw&#xff08;Clawdbot&#xff09;的流程&#xff0c;包含环…...

从零掌握ComfyUI-WanVideoWrapper:AI视频制作工具实战指南

从零掌握ComfyUI-WanVideoWrapper&#xff1a;AI视频制作工具实战指南 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 在数字内容创作领域&#xff0c;视频生成工具正经历着前所未有的技术革新。…...

如何使用CSS自定义属性加速前端开发:Open Props实用指南

如何使用CSS自定义属性加速前端开发&#xff1a;Open Props实用指南 【免费下载链接】open-props CSS custom properties to help accelerate adaptive and consistent design. 项目地址: https://gitcode.com/gh_mirrors/op/open-props Open Props是一个开源的CSS自定义…...

Halcon仿射变换实战:手把手教你用vector_to_aniso和solve_matrix搞定图像配准(附完整代码)

Halcon仿射变换实战&#xff1a;从原理到工程落地的图像配准指南 在工业视觉检测领域&#xff0c;图像配准的精度直接影响着后续缺陷检测的准确性。去年参与的一个半导体封装项目让我深刻体会到这一点——当芯片位置存在0.5像素以上的偏移时&#xff0c;细微的焊球缺陷就会被漏…...

ViGEmBus终极指南:Windows游戏控制器虚拟化完整解决方案

ViGEmBus终极指南&#xff1a;Windows游戏控制器虚拟化完整解决方案 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus Windows游戏控制器虚拟化是许多PC游戏玩…...

23种设计模式 - 组合模式(Composite)

组合模式&#xff08;Composite&#xff09;—— 文件夹套文件夹&#xff0c;统一操作 大白话解释 你的电脑里&#xff1a; &#x1f4c4; 文件&#xff08;不能再包含东西&#xff09;&#x1f4c1; 文件夹&#xff08;可以装文件&#xff0c;也可以装文件夹&#xff09; &…...

如何让实验室管理“更简单”?——King’s LIMS以灵活与智能,重构高效运营新范式

在日常实验室管理中&#xff0c;流程繁琐、数据难溯源、报告生成低效、多场景管控混乱等问题&#xff0c;常成为拖慢运营节奏、抬升运维成本的“隐形阻力”。要打破管理困局、实现轻量化高效运维&#xff0c;选对数字化工具是关键。然而&#xff0c;在选择LIMS的过程中&#xf…...

基于comsol仿真的手性超表面圆二色性分析及其在圆偏振光照射下的响应研究

手性超表面圆二色性comsol仿真 左右旋圆偏振光照射超表面的仿真&#xff0c; 圆二色性的计算 comsol光学仿真最近在折腾手性超表面的仿真&#xff0c;发现用COMSOL搞圆二色性&#xff08;CD&#xff09;计算这事挺有意思的。特别是左右旋圆偏振光打上去之后&#xff0c;结构的手…...

Arco design vue 表格排序踩坑

父组件&#xff1a;<template><div class"p-10"><!-- 商户管理 --><div class"invate-box placeholder:"><div class"flex items-center"><SvgIcon :name"user"></SvgIcon><div class&q…...

APK Editor Studio:从入门到精通的完整Android应用编辑指南

APK Editor Studio&#xff1a;从入门到精通的完整Android应用编辑指南 【免费下载链接】apk-editor-studio Powerful yet easy to use APK editor for PC and Mac. 项目地址: https://gitcode.com/gh_mirrors/ap/apk-editor-studio 在Android应用开发和逆向工程领域&am…...

清单来了:2026最新AI论文网站测评与推荐

2026年真正好用的AI论文网站&#xff0c;核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测&#xff0c;千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队&#xff0c;覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…...

Midscene.js从入门到精通:AI驱动的跨平台自动化技术指南

Midscene.js从入门到精通&#xff1a;AI驱动的跨平台自动化技术指南 【免费下载链接】midscene Let AI be your browser operator. 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 在数字化时代&#xff0c;软件界面的动态变化和跨平台兼容性给自动化测试…...

wflow工作流设计器:5分钟快速上手的企业流程自动化完整指南

wflow工作流设计器&#xff1a;5分钟快速上手的企业流程自动化完整指南 【免费下载链接】wflow workflow 工作流设计器&#xff0c;企业OA流程设计。表单流程设计界面操作超级简单&#xff01;&#xff01;普通用户也能分分钟上手&#xff0c;不需要专业知识。本设计器支持可视…...

好用还专业!盘点2026年备受推崇的一键生成论文工具

一天写完毕业论文在2026年已不再是天方夜谭。最新实测显示&#xff0c;一键生成论文工具正在颠覆传统写作方式&#xff0c;覆盖选题、文献、写作、降重、排版等核心场景&#xff0c;真正实现高效搞定论文&#xff0c;学生党必备神器。 一、全流程王者&#xff1a;一站式搞定论文…...

2026年专业金属链板输送带服务哪家强?TOP排名为你揭晓!

家人们&#xff0c;在工业生产领域&#xff0c;金属链板输送带那可是相当重要的设备&#xff0c;它的质量和服务直接影响着生产效率。今天咱就来聊聊 2026 年专业金属链板输送带服务的那些事儿&#xff0c;给大家揭晓一下排名情况&#xff0c;顺便看看哪家更值得咱们选择。冲突…...

做客户管理之前,先看看这 6 个教训

方案 A&#xff1a;传统开发方式分析 传统开发需要组建专业团队&#xff0c;包括产品经理、UI 设计师、前后端开发、测试工程师等。中等规模项目团队 5-8 人&#xff0c;开发周期 3-6 个月&#xff0c;人力成本 30-100 万。开发过程中需求沟通成本高&#xff0c;业务人员用自然…...

相机潜能解锁:从限制突破到专业创作

相机潜能解锁&#xff1a;从限制突破到专业创作 【免费下载链接】OpenMemories-Tweak Unlock your Sony cameras settings 项目地址: https://gitcode.com/gh_mirrors/op/OpenMemories-Tweak OpenMemories-Tweak作为一款专为索尼相机设计的系统级解锁工具&#xff0c;通…...

Windows 内网 Web 服务穿透方案推荐

Windows 内网 Web 服务穿透方案推荐 面向场景&#xff1a;内网机器为 Windows&#xff0c;需从公网或外网访问内网 HTTP/HTTPS Web 服务&#xff1b;优先选择相对不易被误报、来源清晰、可审计的方案。 关于「报毒」的说明 穿透类软件常被启发式引擎标为「风险/可疑」&#xf…...

AI赋能开发:让快马平台智能解析并生成17.100.c.cm规格的优化代码

最近在做一个需要处理特定规格数据的项目&#xff0c;遇到了一个有趣的开发场景&#xff1a;需要基于"17.100.c.cm"这样的参数组合来构建微服务架构。这个看似简单的字符串其实包含了多维度的技术参数&#xff0c;正好可以借助InsCode(快马)平台的AI辅助开发能力来高…...

如何在Windows上零配置运行Android应用?APK Installer的革命性方案

如何在Windows上零配置运行Android应用&#xff1f;APK Installer的革命性方案 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经遇到过这样的场景&#xff1a…...

如何在群晖NAS上部署百度网盘客户端:终极安装与配置指南

如何在群晖NAS上部署百度网盘客户端&#xff1a;终极安装与配置指南 【免费下载链接】synology-baiduNetdisk-package 项目地址: https://gitcode.com/gh_mirrors/sy/synology-baiduNetdisk-package 还在为群晖NAS与百度网盘之间的文件同步问题而烦恼吗&#xff1f;群晖…...

重构直播互动体验:BLiveChat的跨平台弹幕解决方案

重构直播互动体验&#xff1a;BLiveChat的跨平台弹幕解决方案 【免费下载链接】blivechat 用于OBS的仿YouTube风格的bilibili直播评论栏 项目地址: https://gitcode.com/gh_mirrors/bl/blivechat BLiveChat作为一款开源的B站直播弹幕工具&#xff0c;通过仿YouTube风格的…...

【亲测】OpenClaw怎么部署?2026年OpenClaw华为云8分钟搭建喂奶级教程

【亲测】OpenClaw怎么部署&#xff1f;2026年OpenClaw华为云8分钟搭建喂奶级教程。OpenClaw能做什么&#xff1f;OpenClaw怎么部署&#xff1f;本文面向零基础用户&#xff0c;完整说明在轻量服务器与本地Windows11、macOS、Linux系统中部署OpenClaw&#xff08;Clawdbot&#…...

光伏储能管理系统:绿虫赋能,破解行业流程痛点

光伏储能产业迎来高速发展期&#xff0c;但其全业务流程的复杂性却成为企业发展的桎梏。从项目开发的多环节审批&#xff0c;到建设阶段的进度质量管控&#xff0c;再到运维结算的数据协同&#xff0c;各环节割裂、部门协作不畅、数据杂乱无章等问题频发&#xff0c;不少企业负…...

基于MATLAB的模拟退火粒子群算法在含分布式电源配电网多目标优化中的应用

310.基于matlab的模拟退火粒子群算法对含分布式电源的配电网进行多目标优化&#xff0c;目标函数包括总有功网损、总投资与运行成本、电压稳定欲度。 和目标函数相关参数有单位分布式电源投资成本、运行成本&#xff0c;分布式电源设备使用年限、贴现率等。 经过优化得到最佳结…...

4步实现Android Studio本地化配置:从语言障碍到高效开发

4步实现Android Studio本地化配置&#xff1a;从语言障碍到高效开发 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本&#xff09; 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack 问题诊断&…...

[2026 职场洗牌系列 01] 程序员正在“杀死”自己的工作?科技行业高危预警

长久以来&#xff0c;学计算机&#xff08;CS&#xff09;在很多年轻人眼里就等同于拿到了通往高薪和阶层跃升的金钥匙。大家都觉得&#xff0c;只要把代码敲得溜&#xff0c;这辈子在职场上基本就稳了。可惜&#xff0c;到了2026年的今天&#xff0c;生成式AI正在毫不留情地把…...

英雄联盟智能工具League Akari:提升游戏体验的终极指南

英雄联盟智能工具League Akari&#xff1a;提升游戏体验的终极指南 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari是…...

OpenClaw备份策略:GLM-4.7-Flash智能管理本地与云端存储

OpenClaw备份策略&#xff1a;GLM-4.7-Flash智能管理本地与云端存储 1. 为什么需要智能备份方案 上周我的移动硬盘突然罢工&#xff0c;导致三个月的项目文档全部丢失。这次惨痛经历让我意识到&#xff1a;传统备份方式已经无法满足现代工作需求。手动备份不仅耗时耗力&#…...