前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[正则表达式 ]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
Logstash
...定义匹配下一行开始的正则表达式 what => "previous" 表示当前行与上一行合并 negate => true 匹配失败才合并,对于堆栈跟踪等通常第一行不匹配模式的情况有用 } } } 在这个例子中,codec会根据指定的pattern识别出新的一行日志的开始,并将之前的所有行合并为一个事件。当遇到新的时间戳时,Logstash认为一个新的事件开始了,然后重新开始合并过程。 3. 使用multiline Filter的旧版方案 在Logstash的早期版本中,multiline功能是通过filter插件实现的: ruby input { file { path => "/path/to/your/logs/.log" start_position => "beginning" } } filter { multiline { pattern => "^%{TIMESTAMP_ISO8601}" what => "previous" negate => true } } 尽管在最新版本中这一做法已不再推荐,但在某些场景下,你仍可能需要参考这种旧有的配置方法。 4. 解析多行日志实战思考 在实际应用中,理解并调整multiline配置参数至关重要。比如,这个pattern呐,它就像是个超级侦探,得按照你日志的“穿衣风格”准确无误地找到每一段多行日志的开头标志。再来说说这个what字段,它就相当于我们的小助手,告诉我们哪几行该凑到一块儿去,可能是上一个兄弟,也可能是下一个邻居。最后,还有个灵活的小开关negate,你可以用它来反转匹配规则,这样就能轻松应对各种千奇百怪的日志格式啦! 当你调试多行日志合并规则时,可能会经历一些曲折,因为不同的应用程序可能有着迥异的日志格式。这就需要我们化身成侦探,用敏锐的眼光去洞察,用智慧的大脑去推理,手握正则表达式的“试验田”,不断试错、不断调整优化。直到有一天,我们手中的正则表达式如同一把无比精准的钥匙,咔嚓一声,就打开了与日志结构完美匹配的那扇大门。 总结起来,在Logstash中处理多行日志合并是一个涉及对日志结构深入理解的过程,也是利用Logstash强大灵活性的一个体现。你知道吗,如果我们灵巧地使用multiline这个codec或者filter小工具,就能把那些本来七零八落的上下文信息,像拼图一样拼接起来,对齐得整整齐齐的。这样一来,后面我们再做数据分析时,不仅效率蹭蹭往上涨,而且结果也会准得没话说,简直不要太给力!
2023-08-19 08:55:43
249
春暖花开
Scala
...式。这里我们可以借助正则表达式来完成这一任务: scala import scala.util.matching.Regex val urlRegex: Regex = """https?://[\w.-]+(/[\w.-])""".r def isValidUrl(url: String): Boolean = url match { case urlRegex() => true case _ => false } // 测试 println(isValidUrl("http://example.com")) // 输出: true println(isValidUrl("www.example.com")) // 输出: false 使用try-catch块 其次,在实际创建URL对象时,可以将这部分代码包裹在一个try-catch块中,这样即使发生MalformedURLException,程序也不会完全崩溃,而是能够优雅地处理错误: scala try { val url = new java.net.URL("http://example.com") println(s"URL is valid: $url") } catch { case e: java.net.MalformedURLException => println("MalformedURLException occurred.") } 4. 处理异常 除了基本的异常捕获之外,我们还可以采取一些额外措施来增强程序的鲁棒性。例如,在catch块内部,我们可以记录错误日志,甚至向用户提供友好的提示信息,告知他们输入的URL存在格式问题,并建议正确的格式: scala try { val url = new java.net.URL("http://example.com") println(s"URL is valid: $url") } catch { case e: java.net.MalformedURLException => println("MalformedURLException occurred. Please ensure your URL is properly formatted.") // 记录错误日志 import java.io.PrintWriter import java.io.StringWriter val sw = new StringWriter() val pw = new PrintWriter(sw) e.printStackTrace(pw) println(sw.toString) } 进阶技巧:自定义URL验证函数 5. 自定义验证逻辑 为了进一步提高代码的可读性和复用性,我们可以封装上述功能,创建一个专门用于验证URL的函数。该函数不仅会检查URL格式,还会执行一些额外的安全检查,比如防止SQL注入等恶意行为: scala import java.net.URL def validateUrl(urlString: String): Option[URL] = { if (!isValidUrl(urlString)) { None } else { try { Some(new URL(urlString)) } catch { case _: MalformedURLException => None } } } // 测试 validateUrl("http://example.com") match { case Some(url) => println(s"Valid URL: $url") case None => println("Invalid URL.") } 结论 通过本文的学习,希望大家对Scala中处理URL相关的问题有了更深刻的理解。记住,预防总是优于治疗。在写代码的时候,提前想到可能会出的各种岔子,并且想办法避开它们,这样我们的程序就能更稳当、更靠谱了。当然,面对MalformedURLException这样的常见异常,保持冷静、合理应对同样重要。希望今天的分享能帮助大家写出更好的Scala代码! 最后,别忘了在日常开发中多实践、多总结经验,编程之路虽充满挑战,但每一步都值得骄傲。祝大家代码愉快!
2024-12-19 15:45:26
23
素颜如水
RabbitMQ
...限规则 权限控制通过正则表达式来定义,这意味着你可以非常灵活地控制哪些用户能做什么,不能做什么。比如说,你可以设定某个用户只能看到名字以特定字母开头的队列,或者干脆不让某些用户碰特定的交换机。 3. 实战演练 动手配置权限控制 理论讲完了,接下来就让我们一起动手,看看如何在RabbitMQ中配置权限控制吧! 3.1 创建用户 首先,我们需要创建一些用户。假设我们有两个用户:alice 和 bob。打开命令行工具,输入以下命令: bash rabbitmqctl add_user alice password rabbitmqctl set_user_tags alice administrator rabbitmqctl add_user bob password 这里,alice 被设置为管理员,而 bob 则是普通用户。注意,这里的密码都设为 password,实际使用时可要改得复杂一点哦! 3.2 设置vhost 接着,我们需要创建一个虚拟主机,并分配给这两个用户: bash rabbitmqctl add_vhost my-vhost rabbitmqctl set_permissions -p my-vhost alice "." "." "." rabbitmqctl set_permissions -p my-vhost bob "." "." "." 这里,我们给 alice 和 bob 都设置了通配符权限,也就是说他们可以在 my-vhost 中做任何事情。当然,这只是个示例,实际应用中你肯定不会这么宽松。 3.3 精细调整权限 现在,我们来试试更精细的权限控制。假设我们只想让 alice 能够管理队列,但不让 bob 做这件事。我们可以这样设置: bash rabbitmqctl set_permissions -p my-vhost alice "." "." "." rabbitmqctl set_permissions -p my-vhost bob "." "^bob-queue-" "^bob-queue-" 在这个例子中,alice 可以对所有资源进行操作,而 bob 只能对以 bob-queue- 开头的队列进行读写操作。 3.4 使用API进行权限控制 除了命令行工具外,RabbitMQ还提供了HTTP API来管理权限。例如,要获取特定用户的权限信息,可以发送如下请求: bash curl -u admin:admin-password http://localhost:15672/api/permissions/my-vhost/alice 这里的 admin:admin-password 是你的管理员账号和密码,my-vhost 和 alice 分别是你想要查询的虚拟主机名和用户名。 4. 总结与反思 通过上面的操作,相信你已经对RabbitMQ的权限控制有了一个基本的认识。不过,值得注意的是,权限控制并不是一劳永逸的事情。随着业务的发展,你可能需要不断调整权限设置,以适应新的需求。所以,在设计权限策略的时候,咱们得想远一点,留有余地,这样系统才能长久稳定地运转下去。 最后,别忘了,安全永远是第一位的。就算是再简单的消息队列系统,我们也得弄个靠谱的权限管理,不然咱们的数据安全可就悬了。希望这篇文章对你有所帮助,如果你有任何疑问或建议,欢迎留言交流! --- 这就是今天的分享了,希望大家能够从中获得灵感,并在自己的项目中运用起来。记住啊,不管多复杂的系统,到最后不就是为了让人用起来更方便,生活过得更舒心嘛!加油,程序员朋友们!
2024-12-18 15:31:50
102
梦幻星空
转载文章
...ern属性进行自定义正则表达式合法性校验),进一步简化了表单验证的过程。 近期,GitHub上开源了一款名为“Formik”的库,专门针对React应用中的表单处理,它提供了一套完整的解决方案,包括字段管理、错误处理、异步提交和表单生命周期钩子等功能,极大地提升了开发效率和代码可读性。此外,随着Web API接口的丰富和完善,原生Ajax已经逐渐被Fetch API取代,Fetch提供了更强大的功能和更好的错误处理机制,使得前端与后端数据交互更为流畅。 对于想要进一步提升前端技能的开发者来说,紧跟时下热门的前端UI库如Ant Design、Element UI等对表单组件的封装与优化也是必不可少的学习内容。这些库不仅提供了丰富的表单样式,还内置了诸多实用的功能,如联动选择器、动态加载选项等,有助于打造更为复杂的业务场景表单。 综上所述,前端表单处理是一个持续演进的话题,从基础的DOM操作到利用现代框架和API提升开发体验,再到借鉴优秀开源项目的设计思想,都是值得前端开发者关注并深入探索的方向。
2023-10-22 17:32:41
521
转载
转载文章
...t.close() 正则表达式使用 import res = "pythonxxxxxxpython"result = re.match("python",s) 从左到右匹配print(result) <re.Match object; span=(0, 6), match='python'>print(result.span()) (0, 6)print(result.group()) pythonresult = re.search("python",s) 匹配到第一个print(result) <re.Match object; span=(0, 6), match='python'>result = re.findall("python",s) 匹配全部print(result) ['python', 'python'] 单字符匹配 数量匹配 边界匹配 分组匹配 pattern = "1[35678]\d{9}"phoneStr = "15288888888"result = re.match(pattern, phoneStr)print(result) <re.Match object; span=(0, 11), match='15288888888'> 递归 递归显示目录中文件 import osdef get_files_recursion_dir(path):file_list = []if os.path.exists(path):for f in os.listdir(path):new_path = path + "/" + fif os.path.isdir(new_path):file_list += get_files_recursion_dir(new_path)else:file_list.append(new_path)else:print(f"指定的目录{path},不存在")return []return file_listif __name__ == '__main__':print(get_files_recursion_dir("D:\test")) 本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_29385297/article/details/128085103。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-05-28 18:35:16
90
转载
Logstash
...件整点儿花样,比如说正则表达式匹配或者修改字段之类的。最后,它还支持不少输出插件,比如往Elasticsearch或者Kafka里面扔数据,简直不要太方便!这种灵活性使得Logstash成为了处理复杂数据流的理想选择。 1.2 Elasticsearch:实时搜索与分析的利器 Elasticsearch 是一个基于Lucene构建的开源分布式搜索引擎,它提供了强大的全文搜索功能,同时也支持结构化搜索、数值搜索以及地理空间搜索等多种搜索类型。此外,Elasticsearch还拥有出色的实时分析能力,这得益于其独特的倒排索引机制。当你将数据导入Elasticsearch后,它会自动对数据进行索引,从而大大提高了查询速度。 2. 实时索引优化 让数据飞起来 现在我们已经了解了Logstash和Elasticsearch各自的特点,接下来就让我们看看如何通过它们来实现高效的实时索引优化吧! 2.1 数据采集与预处理 首先,我们需要利用Logstash从各种数据源采集数据。好嘞,咱们换个说法:比如说,我们要从服务器的日志里挖出点儿有用的东西,就像找宝藏一样,目标就是那些访问时间、用户ID和请求的网址这些信息。我们可以用Filebeat这个工具来读取日志文件,然后再用Grok这个插件来解析这些数据,让信息变得更清晰易懂。下面是一个具体的配置示例: yaml input { file { path => "/var/log/nginx/access.log" start_position => "beginning" } } filter { grok { match => { "message" => "%{COMBINEDAPACHELOG}" } } } 这段配置告诉Logstash,从/var/log/nginx/access.log这个路径下的日志文件开始读取,并使用Grok插件中的COMBINEDAPACHELOG模式来解析每一行日志内容。这样子一来,原始的文本信息就被拆成了一个个有组织的小块儿,给接下来的处理铺平了道路,简直不要太方便! 2.2 高效索引策略 一旦数据被Logstash处理完毕,下一步就是将其导入Elasticsearch。为了确保索引操作尽可能高效,我们可以采取一些策略: - 批量处理:减少网络往返次数,提高吞吐量。 - 动态映射:允许Elasticsearch根据文档内容自动创建字段类型,简化索引管理。 - 分片与副本:合理设置分片数量和副本数量,平衡查询性能与集群稳定性。 下面是一个简单的Logstash输出配置示例,演示了如何将处理后的数据批量发送给Elasticsearch: yaml output { elasticsearch { hosts => ["localhost:9200"] index => "nginx-access-%{+YYYY.MM.dd}" document_type => "_doc" user => "elastic" password => "changeme" manage_template => false template => "/path/to/template.json" template_name => "nginx-access" template_overwrite => true flush_size => 5000 idle_flush_time => 1 } } 在这段配置中,我们设置了批量大小为5000条记录,以及空闲时间阈值为1秒,这意味着当达到这两个条件之一时,Logstash就会将缓冲区内的数据一次性发送至Elasticsearch。此外,我还指定了自定义的索引模板,以便更好地控制字段映射规则。 3. 实战案例 打造高性能日志分析平台 好了,理论讲得差不多了,接下来让我们通过一个实际的例子来看看这一切是如何运作的吧! 假设你是一家电商网站的运维工程师,最近你们网站频繁出现访问异常的问题,客户投诉不断。为了找出问题根源,你需要对Nginx服务器的日志进行深入分析。幸运的是,你们已经部署了Logstash和Elasticsearch作为日志处理系统。 3.1 日志采集与预处理 首先,我们需要确保Logstash能够正确地从Nginx服务器上采集到所有相关的日志信息。根据上面说的设置,我们可以搞一个Logstash配置文件,用来从特定的日志文件里扒拉出重要的信息。嘿,为了让大家看日志的时候能更轻松明了,我们可以加点小技巧,比如说统计每个用户逛网站的频率,或者找出那些怪怪的访问模式啥的。这样一来,信息就一目了然啦! 3.2 索引优化与查询分析 接下来,我们将这些处理后的数据发送给Elasticsearch进行索引存储。有了合适的索引设置,就算同时来一大堆请求,我们的查询也能嗖嗖地快,不会拖泥带水的。比如说,在上面那个输出配置的例子里面,我们调高了批量处理的门槛,同时把空闲时间设得比较短,这样就能大大加快数据写入的速度啦! 一旦数据被成功索引,我们就可以利用Elasticsearch的强大查询功能来进行深度分析了。比如说,你可以写个DSL查询,找出最近一周内访问量最大的10个页面;或者,你还可以通过用户ID捞出某个用户的操作记录,看看能不能从中发现问题。 4. 结语 拥抱变化,不断探索 通过以上介绍,相信大家已经对如何使用Logstash与Elasticsearch实现高效的实时索引优化有了一个全面的认识。当然啦,技术这东西总是日新月异的,所以我们得保持一颗好奇的心,不停地学新技术,这样才能更好地迎接未来的各种挑战嘛! 希望这篇文章能对你有所帮助,如果你有任何疑问或建议,欢迎随时留言交流。让我们一起加油,共同成长!
2024-12-17 15:55:35
41
追梦人
转载文章
...世界协调时间。 2、正则表达式 假设用户需要在 HTML 表单中填写姓名、地址、出生日期等。那么在将表单提交到服务器进一步处理前,JavaScript 程序会检查表单以确认用户确实输入了信息并且这些信息是符合要求的。 什么是正则表达式 正则表达式(regular expression)是一个描述字符模式的对象。ECMAScript 的 RegExp 类表示正则表达式,而 String 和 RegExp 都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数。 正则表达式主要用来验证客户端的输入数据。用户填写完表单单击按钮之后,表单就会被发送到服务器,在服务器端通常会用 PHP、ASP.NET 等服务器脚本对其进行进一步处理 。因为客户端验证,可以节约大量的服务器端的系统资源,并且提供更好的用户体验。 创建正则表达式 创建正则表达式和创建字符串类似,创建正则表达式提供了两种方法,一种是采用 new 运算符,另一个是采用字面量方式。 两种创建方式 var box = new RegExp('box'); // 第一个参数字符串var box = new RegExp('box', 'ig'); // 第二个参数可选模式修饰符 模式修饰符的可选参数 参数 含义 i 忽略大小写 g 全局匹配 m 多行匹配 var box = /box/; // 直接用两个反斜杠var box = /box/ig; // 在第二个斜杠后面加上模式修饰符 测试正则表达式 RegExp 对象包含两个方法:test()和 exec(),功能基本相似,用于测试字符串匹配。test()方法在字符串中查找是否存在指定的正则表达式并返回布尔值,如果存在则返回 true,不存在则返回 false。exec()方法也用于在字符串中查找指定正则表达式,如果 exec()方法执行成功,则返回包含该查找字符串的相关信息数组。如果执行失败,则返回 null。 RegExp 对象的方法 方法 功能 test 在字符串中测试模式匹配,返回 true 或 false exec 在字符串中执行匹配搜索,返回结果数组 // 使用 new 运算符的 test 方法示例var pattern = new RegExp('box', 'i'); // 创建正则模式,不区分大小写var str = 'This is a Box!'; // 创建要比对的字符串alert(pattern.test(str)); // 通过 test()方法验证是否匹配// 使用字面量方式的 test 方法示例var pattern = /box/i; // 创建正则模式,不区分大小写var str = 'This is a Box!';alert(pattern.test(str));// 使用一条语句实现正则匹配alert(/box/i.test('This is a Box!')); // 模式和字符串替换掉了两个变量// 使用 exec 返回匹配数组var pattern = /box/i;var str = 'This is a Box!';alert(pattern.exec(str)); // 匹配了返回数组,否则返回 null 使用字符串的正则表达式方法 除了 test()和 exec()方法,String 对象也提供了 4 个使用正则表达式的方法。 String 对象中的正则表达式方法 方法 含义 match(pattern) 返回 pattern 中的子串或 null replace(pattern, replacement) 用 replacement 替换 pattern search(pattern) 返回字符串中 pattern 开始位置 split(pattern) 返回字符串按指定 pattern 拆分的数组 // 使用 match 方法获取获取匹配数组var pattern = /box/ig; // 全局搜索var str = 'This is a Box!,That is a Box too';alert(str.match(pattern)); // 匹配到两个 Box,Boxalert(str.match(pattern).length); // 获取数组的长度// 使用 search 来查找匹配数据var pattern = /box/ig;var str = 'This is a Box!,That is a Box too';alert(str.search(pattern)); // 查找到返回位置,否则返回-1 因为 search 方法查找到即返回,也就是说无需 g 全局。 // 使用 replace 替换匹配到的数据var pattern = /box/ig;var str = 'This is a Box!,That is a Box too';alert(str.replace(pattern, 'Tom')); // 将 Box 替换成了 Tom// 使用 split 拆分成字符串数组var pattern = / /ig;var str = 'This is a Box!,That is a Box too';alert(str.split(pattern)); // 将空格拆开分组成数组 RegExp 对象的静态属性 属性 短名 含义 input $_ 当前被匹配的字符串 lastMatch $& 最后一个匹配字符串 lastParen $+ 最后一对圆括号内的匹配子串 leftContext $ 最后一次匹配前的子串 multiline $ 用于指定是否所有的表达式都用于多行的布尔值 rightContext $’ 在上次匹配之后的子串 // 使用静态属性var pattern = /(g)oogle/;var str = 'This is google!';pattern.test(str); // 执行一下alert(RegExp.input); // This is google!alert(RegExp.leftContext); // This isalert(RegExp.rightContext); // !alert(RegExp.lastMatch); // googlealert(RegExp.lastParen); // galert(RegExp.multiline); // false Opera 不支持 input、lastMatch、lastParen 和 multiline 属性。IE 不支持 multiline 属性。所有的属性可以使用短名来操作。RegExp.input 可以改写成 RegExp['$_'],依次类推。但 RegExp.input 比较特殊,它还可以写成 RegExp.$_。 RegExp 对象的实例属性 属性 含义 global Boolean 值,表示 g 是否已设置 ignoreCase Boolean 值,表示 i 是否已设置 lastIndex 整数,代表下次匹配将从哪里字符位置开始 multiline Boolean 值,表示 m 是否已设置 Source 正则表达式的源字符串形式 // 使用实例属性var pattern = /google/ig;alert(pattern.global); // true,是否全局了alert(pattern.ignoreCase); // true,是否忽略大小写alert(pattern.multiline); // false,是否支持换行alert(pattern.lastIndex); // 0,下次的匹配位置alert(pattern.source); // google,正则表达式的源字符串var pattern = /google/g;var str = 'google google google';pattern.test(str); // google,匹配第一次alert(pattern.lastIndex); // 6,第二次匹配的位 以上基本没什么用。并且 lastIndex 在获取下次匹配位置上 IE 和其他浏览器有偏差 ,主要表现在非全局匹配上。lastIndex 还支持手动设置,直接赋值操作。 获取控制 正则表达式元字符是包含特殊含义的字符。它们有一些特殊功能,可以控制匹配模式的方式。反斜杠后的元字符将失去其特殊含义。 字符类:单个字符和数字 元字符/元符号 匹配情况 . 匹配除换行符外的任意字符 [a-z0-9] 匹配括号中的字符集中的任意字符 [^a-z0-9] 匹配任意不在括号中的字符集中的字符 \d 匹配数字 \D 匹配非数字,同[^0-9]相同 \w 匹配字母和数字及_ \W 匹配非字母和数字及_ 字符类:空白字符 元字符/元符号 匹配情况 \0 匹配 null 字符 \b 匹配空格字符 \f 匹配进纸字符 \n 匹配换行符 \r 匹配回车字符 \t 匹配制表符 \s 匹配空白字符、空格、制表符和换行符 \S 匹配非空白字符 字符类:锚字符 元字符/元符号 匹配情况 ^ 行首匹配 $ 行尾匹配 \A 只有匹配字符串开始处 \b 匹配单词边界,词在[]内时无效 \B 匹配非单词边界 \G 匹配当前搜索的开始位置 \Z 匹配字符串结束处或行尾 \z 只匹配字符串结束处 字符类:重复字符 元字符/元符号 匹配情况 x? 匹配 0 个或 1 个 x x 匹配 0 个或任意多个 x x+ 匹配至少一个 x (xyz)+ 匹配至少一个(xyz) x{m,n} 匹配最少 m 个、最多 n 个 x 字符类:替代字符 元字符/元符号 匹配情况 this where 字符类:记录字符 元字符/元符号 匹配情况 (string) 用于反向引用的分组 \1 或$1 匹配第一个分组中的内容 \2 或$2 匹配第二个分组中的内容 \3 或$3 匹配第三个分组中的内容 // 使用点元字符var pattern = /g..gle/; // .匹配一个任意字符var str = 'google';alert(pattern.test(str));// 重复匹配var pattern = /g.gle/; // .匹配 0 个一个或多个var str = 'google'; //,?,+,{n,m}alert(pattern.test(str));// 使用字符类匹配var pattern = /g[a-zA-Z_]gle/; // [a-z]表示任意个 a-z 中的字符var str = 'google';alert(pattern.test(str));var pattern = /g[^0-9]gle/; // [^0-9]表示任意个非 0-9 的字符var str = 'google';alert(pattern.test(str));var pattern = /[a-z][A-Z]+/; // [A-Z]+表示 A-Z 一次或多次var str = 'gOOGLE';alert(pattern.test(str));// 使用元符号匹配var pattern = /g\wgle/; // \w匹配任意多个所有字母数字_var str = 'google';alert(pattern.test(str));var pattern = /google\d/; // \d匹配任意多个数字var str = 'google444';alert(pattern.test(str));var pattern = /\D{7,}/; // \D{7,}匹配至少 7 个非数字var str = 'google8';alert(pattern.test(str));// 使用锚元字符匹配var pattern = /^google$/; // ^从开头匹配,$从结尾开始匹配var str = 'google';alert(pattern.test(str));var pattern = /goo\sgle/; // \s 可以匹配到空格var str = 'goo gle';alert(pattern.test(str));var pattern = /google\b/; // \b 可以匹配是否到了边界var str = 'google';alert(pattern.test(str));// 使用或模式匹配var pattern = /google|baidu|bing/; // 匹配三种其中一种字符串var str = 'google';alert(pattern.test(str));// 使用分组模式匹配var pattern = /(google){4,8}/; // 匹配分组里的字符串 4-8 次var str = 'googlegoogle';alert(pattern.test(str));var pattern = /8(.)8/; // 获取 8..8 之间的任意字符var str = 'This is 8google8';str.match(pattern);alert(RegExp.$1); // 得到第一个分组里的字符串内容var pattern = /8(.)8/;var str = 'This is 8google8';var result = str.replace(pattern,'<strong>$1</strong>'); // 得到替换的字符串输出document.write(result);var pattern = /(.)\s(.)/;var str = 'google baidu';var result = str.replace(pattern, '$2 $1'); // 将两个分组的值替换输出document.write(result); 贪婪 惰性 + +? ? ?? ? {n} {n}? {n,} {n,}? {n,m} {n,m}? // 关于贪婪和惰性var pattern = /[a-z]+?/; // ?号关闭了贪婪匹配,只替换了第一个var str = 'abcdefjhijklmnopqrstuvwxyz';var result = str.replace(pattern, 'xxx');alert(result);var pattern = /8(.+?)8/g; // 禁止了贪婪,开启的全局var str = 'This is 8google8, That is 8google8, There is 8google8';var result = str.replace(pattern,'<strong>$1</strong>');document.write(result);var pattern = /8([^8])8/g; // 另一种禁止贪婪var str = 'This is 8google8, That is 8google8, There is 8google8';var result = str.replace(pattern,'<strong>$1</strong>');document.write(result);// 使用 exec 返回数组var pattern = /^[a-z]+\s[0-9]{4}$/i;var str = 'google 2012';alert(pattern.exec(str)); // 返回整个字符串var pattern = /^[a-z]+/i; // 只匹配字母var str = 'google 2012';alert(pattern.exec(str)); // 返回 googlevar pattern = /^([a-z]+)\s([0-9]{4})$/i; // 使用分组var str = 'google 2012';alert(pattern.exec(str)[0]); // google 2012alert(pattern.exec(str)[1]); // googlealert(pattern.exec(str)[2]); // 2012// 捕获性分组和非捕获性分组var pattern = /(\d+)([a-z])/; // 捕获性分组var str = '123abc';alert(pattern.exec(str));var pattern = /(\d+)(?:[a-z])/; // 非捕获性分组var str = '123abc';alert(pattern.exec(str));// 使用分组嵌套var pattern = /(A?(B?(C?)))/; // 从外往内获取var str = 'ABC';alert(pattern.exec(str));// 使用前瞻捕获var pattern = /(goo(?=gle))/; // goo 后面必须跟着 gle 才能捕获var str = 'google';alert(pattern.exec(str));// 使用特殊字符匹配var pattern = /\.\[\/b\]/; // 特殊字符,用\符号转义即可var str = '.[/b]';alert(pattern.test(str));// 使用换行模式var pattern = /^\d+/mg; // 启用了换行模式var str = '1.baidu\n2.google\n3.bing';var result = str.replace(pattern, '');alert(result); 常用的正则 检查邮政编码 var pattern = /[1-9][0-9]{5}/; // 共 6 位数字,第一位不能为 0var str = '224000';alert(pattern.test(str)); 检查文件压缩包 var pattern = /[\w]+\.zip|rar|gz/; // \w 表示所有数字和字母加下划线var str = '123.zip'; // \.表示匹配.,后面是一个选择alert(pattern.test(str)); 删除多余空格 var pattern = /\s/g; // g 必须全局,才能全部匹配var str = '111 222 333';var result = str.replace(pattern,''); // 把空格匹配成无空格alert(result); 删除首尾空格 var pattern = /^\s+/; // 强制首var str = ' goo gle ';var result = str.replace(pattern, '');pattern = /\s+$/; // 强制尾result = result.replace(pattern, '');alert('|' + result + '|');var pattern = /^\s(.+?)\s$/; // 使用了非贪婪捕获var str = ' google ';alert('|' + pattern.exec(str)[1] + '|');var pattern = /^\s(.+?)\s$/;var str = ' google ';alert('|' + str.replace(pattern, '$1') + '|'); // 使用了分组获取 简单的电子邮件验证 var pattern = /^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9_\.\-]+)\.([a-zA-Z]{2,4})$/;var str = 'yc60.com@gmail.com';alert(pattern.test(str));var pattern = /^([\w\.\-]+)@([\w\.\-]+)\.([\w]{2,4})$/;var str = 'yc60.com@gmail.com';alert(pattern.test(str)); 3、Function类型 在 ECMAScript 中,Function(函数)类型实际上是对象。每个函数都是 Function 类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。 函数的声明方式 普通的函数声明 function box(num1, num2) {return num1+ num2;} 使用变量初始化函数 var box= function(num1, num2) {return num1 + num2;}; 使用 Function 构造函数 var box= new Function('num1', 'num2' ,'return num1 + num2'); 第三种方式我们不推荐,因为这种语法会导致解析两次代码(第一次解析常规 ECMAScript 代码,第二次是解析传入构造函数中的字符串),从而影响性能。但我们可以通过这种语法来理解"函数是对象,函数名是指针"的概念。 作为值的函数 ECMAScript 中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。 function box(sumFunction, num) {return sumFunction(num); // someFunction}function sum(num) {return num + 10;}var result = box(sum, 10); // 传递函数到另一个函数里 函数内部属性 在函数内部,有两个特殊的对象:arguments 和 this。arguments 是一个类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数。但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。 function box(num) {if (num <= 1) {return 1;} else {return num box(num-1); // 一个简单的的递归} } 对于阶乘函数一般要用到递归算法,所以函数内部一定会调用自身;如果函数名不改变是没有问题的,但一旦改变函数名,内部的自身调用需要逐一修改。为了解决这个问题,我们可以使用 arguments.callee 来代替。 function box(num) {if (num <= 1) {return 1;} else {return num arguments.callee(num-1); // 使用 callee 来执行自身} } 函数内部另一个特殊对象是 this,其行为与 Java 和 C中的 this 大致相似。换句话说 ,this 引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域。当在全局作用域中调用函数时,this 对象引用的就是 window。 // 便于理解的改写例子window.color = '红色的'; // 全局的,或者 var color = '红色的';也行alert(this.color); // 打印全局的 colorvar box = {color : '蓝色的', // 局部的 colorsayColor : function () {alert(this.color); // 此时的 this 只能 box 里的 color} };box.sayColor(); // 打印局部的 coloralert(this.color); // 还是全局的// 引用教材的原版例子window.color = '红色的'; // 或者 var color = '红色的';也行var box = {color : '蓝色的'};function sayColor() {alert(this.color); // 这里第一次在外面,第二次在 box 里面}getColor();box.sayColor = sayColor; // 把函数复制到 box 对象里,成为了方法box.sayColor(); 函数属性和方法 ECMAScript 中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性 :length 和 prototype。其中,length 属性表示函数希望接收的命名参数的个数。 function box(name, age) {alert(name + age);}alert(box.length); // 2 对于 prototype 属性,它是保存所有实例方法的真正所在,也就是原型。这个属性 ,我们将在面向对象一章详细介绍。而 prototype 下有两个方法:apply()和 call(),每个函数都包含这两个非继承而来的方法。这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。 function box(num1, num2) {return num1 + num2; // 原函数}function sayBox(num1, num2) {return box.apply(this, [num1, num2]); // this 表示作用域,这里是 window} // []表示 box 所需要的参数function sayBox2(num1, num2) {return box.apply(this, arguments); // arguments 对象表示 box 所需要的参数}alert(sayBox(10,10)); // 20alert(sayBox2(10,10)); // 20 call()方法于 apply()方法相同,他们的区别仅仅在于接收参数的方式不同。对于 call()方法而言,第一个参数是作用域,没有变化,变化只是其余的参数都是直接传递给函数的。 function box(num1, num2) {return num1 + num2;}function callBox(num1, num2) {return box.call(this, num1, num2); // 和 apply 区别在于后面的传参}alert(callBox(10,10)); 事实上,传递参数并不是 apply()和 call()方法真正的用武之地;它们经常使用的地方是能够扩展函数赖以运行的作用域。 var color = '红色的'; // 或者 window.color = '红色的';也行var box = {color : '蓝色的'};function sayColor() {alert(this.color);}sayColor(); // 作用域在 windowsayColor.call(this); // 作用域在 windowsayColor.call(window); // 作用域在 windowsayColor.call(box); // 作用域在 box,对象冒充 这个例子是之前作用域理解的例子修改而成,我们可以发现当我们使用 call(box)方法的时候,sayColor()方法的运行环境已经变成了 box 对象里了。 使用 call()或者 apply()来扩充作用域的最大好处,就是对象不需要与方法发生任何耦合关系(耦合,就是互相关联的意思,扩展和维护会发生连锁反应)。也就是说,box 对象和 sayColor()方法之间不会有多余的关联操作,比如 box.sayColor = sayColor;。 本篇文章为转载内容。原文链接:https://blog.csdn.net/gongxifacai_believe/article/details/108286196。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-01-24 13:01:25
529
转载
转载文章
...变量的类型,例如使用正则表达式进行一些匹配处理。 对进入数据库的特殊字符(’,",\,<,>,&,,; 等)进行转义处理,或编码转换。基本上所有的后端语言都有对字符串进行转义处理的方法,比如 lodash 的 lodash._escapehtmlchar 库。 所有的查询语句建议使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中,即不要直接拼接 SQL 语句。例如 Node.js 中的 mysqljs 库的 query 方法中的 ? 占位参数。 mysql.query(SELECT FROM user WHERE username = ? AND psw = ?, [username, psw]); 在应用发布之前建议使用专业的 SQL 注入检测工具进行检测,以及时修补被发现的 SQL 注入漏洞。网上有很多这方面的开源工具,例如 sqlmap、SQLninja 等。 避免网站打印出 SQL 错误信息,比如类型错误、字段不匹配等,把代码里的 SQL 语句暴露出来,以防止攻击者利用这些错误信息进行 SQL 注入。 不要过于细化返回的错误信息,如果目的是方便调试,就去使用后端日志,不要在接口上过多的暴露出错信息,毕竟真正的用户不关心太多的技术细节,只要话术合理就行。 碰到要操作的数据库的代码,一定要慎重,小心使得万年船,多找几个人多来几次 code review,将问题都暴露出来,而且要善于利用工具,操作数据库相关的代码属于机密,没事不要去各种论坛晒自家站点的 SQL 语句,万一被人盯上了呢? 命令行注入 命令行注入漏洞,指的是攻击者能够通过 HTTP 请求直接侵入主机,执行攻击者预设的 shell 命令,听起来好像匪夷所思,这往往是 Web 开发者最容易忽视但是却是最危险的一个漏洞之一,看一个实例: 假如现在需要实现一个需求:用户提交一些内容到服务器,然后在服务器执行一些系统命令去产出一个结果返回给用户,接口的部分实现如下: // 以 Node.js 为例,假如在接口中需要从 github 下载用户指定的 repoconst exec = require('mz/child_process').exec;let params = {/ 用户输入的参数 /};exec(git clone ${params.repo} /some/path); 这段代码确实能够满足业务需求,正常的用户也确实能从指定的 git repo 上下载到想要的代码,可是和 SQL 注入一样,这段代码在恶意攻击者眼中,简直就是香饽饽。 如果 params.repo 传入的是 https://github.com/zoumiaojiang/zoumiaojiang.github.io.git 当然没问题了。 可是如果 params.repo 传入的是 https://github.com/xx/xx.git && rm -rf / && 恰好你的服务是用 root 权限起的就惨了。 具体恶意攻击者能用命令行注入干什么也像 SQL 注入一样,手法是千变万化的,比如「反弹 shell 注入」等,但原理都是一样的,我们绝对有能力防止命令行注入发生。防止命令行注入需要做到以下几件事情: 后端对前端提交内容需要完全选择不相信,并且对其进行规则限制(比如正则表达式)。 在调用系统命令前对所有传入参数进行命令行参数转义过滤。 不要直接拼接命令语句,借助一些工具做拼接、转义预处理,例如 Node.js 的 shell-escape npm 包。 还是前面的例子,我们可以做到如下: const exec = require('mz/child_process').exec;// 借助 shell-escape npm 包解决参数转义过滤问题const shellescape = require('shell-escape');let params = {/ 用户输入的参数 /};// 先过滤一下参数,让参数符合预期if (!/正确的表达式/.test(params.repo)) {return;}let cmd = shellescape(['git','clone',params.repo,'/some/path']);// cmd 的值: git clone 'https://github.com/xx/xx.git && rm -rf / &&' /some/path// 这样就不会被注入成功了。exec(cmd); DDoS 攻击 DDoS 又叫分布式拒绝服务,全称 Distributed Denial of Service,其原理就是利用大量的请求造成资源过载,导致服务不可用,这个攻击应该不能算是安全问题,这应该算是一个另类的存在,因为这种攻击根本就是耍流氓的存在,「伤敌一千,自损八百」的行为。出于保护 Web App 不受攻击的攻防角度,还是介绍一下 DDoS 攻击吧,毕竟也是挺常见的。 DDoS 攻击可以理解为:「你开了一家店,隔壁家点看不惯,就雇了一大堆黑社会人员进你店里干坐着,也不消费,其他客人也进不来,导致你营业惨淡」。为啥说 DDoS 是个「伤敌一千,自损八百」的行为呢?毕竟隔壁店还是花了不少钱雇黑社会但是啥也没得到不是?DDoS 攻击的目的基本上就以下几个: 深仇大恨,就是要干死你 敲诈你,不给钱就干你 忽悠你,不买我防火墙服务就会有“人”继续干你 也许你的站点遭受过 DDoS 攻击,具体什么原因怎么解读见仁见智。DDos 攻击从层次上可分为网络层攻击与应用层攻击,从攻击手法上可分为快型流量攻击与慢型流量攻击,但其原理都是造成资源过载,导致服务不可用。 网络层 DDoS 网络层 DDos 攻击包括 SYN Flood、ACK Flood、UDP Flood、ICMP Flood 等。 SYN Flood 攻击 SYN flood 攻击主要利用了 TCP 三次握手过程中的 Bug,我们都知道 TCP 三次握手过程是要建立连接的双方发送 SYN,SYN + ACK,ACK 数据包,而当攻击方随意构造源 IP 去发送 SYN 包时,服务器返回的 SYN + ACK 就不能得到应答(因为 IP 是随意构造的),此时服务器就会尝试重新发送,并且会有至少 30s 的等待时间,导致资源饱和服务不可用,此攻击属于慢型 DDoS 攻击。 ACK Flood 攻击 ACK Flood 攻击是在 TCP 连接建立之后,所有的数据传输 TCP 报文都是带有 ACK 标志位的,主机在接收到一个带有 ACK 标志位的数据包的时候,需要检查该数据包所表示的连接四元组是否存在,如果存在则检查该数据包所表示的状态是否合法,然后再向应用层传递该数据包。如果在检查中发现该数据包不合法,例如该数据包所指向的目的端口在本机并未开放,则主机操作系统协议栈会回应 RST 包告诉对方此端口不存在。 UDP Flood 攻击 UDP flood 攻击是由于 UDP 是一种无连接的协议,因此攻击者可以伪造大量的源 IP 地址去发送 UDP 包,此种攻击属于大流量攻击。正常应用情况下,UDP 包双向流量会基本相等,因此发起这种攻击的攻击者在消耗对方资源的时候也在消耗自己的资源。 ICMP Flood 攻击 ICMP Flood 攻击属于大流量攻击,其原理就是不断发送不正常的 ICMP 包(所谓不正常就是 ICMP 包内容很大),导致目标带宽被占用,但其本身资源也会被消耗。目前很多服务器都是禁 ping 的(在防火墙在可以屏蔽 ICMP 包),因此这种攻击方式已经落伍。 网络层 DDoS 防御 网络层的 DDoS 攻击究其本质其实是无法防御的,我们能做得就是不断优化服务本身部署的网络架构,以及提升网络带宽。当然,还是做好以下几件事也是有助于缓解网络层 DDoS 攻击的冲击: 网络架构上做好优化,采用负载均衡分流。 确保服务器的系统文件是最新的版本,并及时更新系统补丁。 添加抗 DDos 设备,进行流量清洗。 限制同时打开的 SYN 半连接数目,缩短 SYN 半连接的 Timeout 时间。 限制单 IP 请求频率。 防火墙等防护设置禁止 ICMP 包等。 严格限制对外开放的服务器的向外访问。 运行端口映射程序或端口扫描程序,要认真检查特权端口和非特权端口。 关闭不必要的服务。 认真检查网络设备和主机/服务器系统的日志。只要日志出现漏洞或是时间变更,那这台机器就可能遭到了攻击。 限制在防火墙外与网络文件共享。这样会给黑客截取系统文件的机会,主机的信息暴露给黑客,无疑是给了对方入侵的机会。 加钱堆机器。。 报警。。 应用层 DDoS 应用层 DDoS 攻击不是发生在网络层,是发生在 TCP 建立握手成功之后,应用程序处理请求的时候,现在很多常见的 DDoS 攻击都是应用层攻击。应用层攻击千变万化,目的就是在网络应用层耗尽你的带宽,下面列出集中典型的攻击类型。 CC 攻击 当时绿盟为了防御 DDoS 攻击研发了一款叫做 Collapasar 的产品,能够有效的防御 SYN Flood 攻击。黑客为了挑衅,研发了一款 Challenge Collapasar 攻击工具(简称 CC)。 CC 攻击的原理,就是针对消耗资源比较大的页面不断发起不正常的请求,导致资源耗尽。因此在发送 CC 攻击前,我们需要寻找加载比较慢,消耗资源比较多的网页,比如需要查询数据库的页面、读写硬盘文件的等。通过 CC 攻击,使用爬虫对某些加载需要消耗大量资源的页面发起 HTTP 请求。 DNS Flood DNS Flood 攻击采用的方法是向被攻击的服务器发送大量的域名解析请求,通常请求解析的域名是随机生成或者是网络世界上根本不存在的域名,被攻击的DNS 服务器在接收到域名解析请求的时候首先会在服务器上查找是否有对应的缓存,如果查找不到并且该域名无法直接由服务器解析的时候,DNS 服务器会向其上层 DNS 服务器递归查询域名信息。域名解析的过程给服务器带来了很大的负载,每秒钟域名解析请求超过一定的数量就会造成 DNS 服务器解析域名超时。 根据微软的统计数据,一台 DNS 服务器所能承受的动态域名查询的上限是每秒钟 9000 个请求。而我们知道,在一台 P3 的 PC 机上可以轻易地构造出每秒钟几万个域名解析请求,足以使一台硬件配置极高的 DNS 服务器瘫痪,由此可见 DNS 服务器的脆弱性。 HTTP 慢速连接攻击 针对 HTTP 协议,先建立起 HTTP 连接,设置一个较大的 Conetnt-Length,每次只发送很少的字节,让服务器一直以为 HTTP 头部没有传输完成,这样连接一多就很快会出现连接耗尽。 应用层 DDoS 防御 判断 User-Agent 字段(不可靠,因为可以随意构造) 针对 IP + cookie,限制访问频率(由于 cookie 可以更改,IP 可以使用代理,或者肉鸡,也不可靠) 关闭服务器最大连接数等,合理配置中间件,缓解 DDoS 攻击。 请求中添加验证码,比如请求中有数据库操作的时候。 编写代码时,尽量实现优化,并合理使用缓存技术,减少数据库的读取操作。 加钱堆机器。。 报警。。 应用层的防御有时比网络层的更难,因为导致应用层被 DDoS 攻击的因素非常多,有时往往是因为程序员的失误,导致某个页面加载需要消耗大量资源,有时是因为中间件配置不当等等。而应用层 DDoS 防御的核心就是区分人与机器(爬虫),因为大量的请求不可能是人为的,肯定是机器构造的。因此如果能有效的区分人与爬虫行为,则可以很好地防御此攻击。 其他 DDoS 攻击 发起 DDoS 也是需要大量的带宽资源的,但是互联网就像森林,林子大了什么鸟都有,DDoS 攻击者也能找到其他的方式发起廉价并且极具杀伤力的 DDoS 攻击。 利用 XSS 举个例子,如果 12306 页面有一个 XSS 持久型漏洞被恶意攻击者发现,只需在春节抢票期间在这个漏洞中执行脚本使得往某一个小站点随便发点什么请求,然后随着用户访问的增多,感染用户增多,被攻击的站点自然就会迅速瘫痪了。这种 DDoS 简直就是无本万利,不用惊讶,现在大站有 XSS 漏洞的不要太多。 来自 P2P 网络攻击 大家都知道,互联网上的 P2P 用户和流量都是一个极为庞大的数字。如果他们都去一个指定的地方下载数据,成千上万的真实 IP 地址连接过来,没有哪个设备能够支撑住。拿 BT 下载来说,伪造一些热门视频的种子,发布到搜索引擎,就足以骗到许多用户和流量了,但是这只是基础攻击。 高级的 P2P 攻击,是直接欺骗资源管理服务器。如迅雷客户端会把自己发现的资源上传到资源管理服务器,然后推送给其它需要下载相同资源的用户,这样,一个链接就发布出去。通过协议逆向,攻击者伪造出大批量的热门资源信息通过资源管理中心分发出去,瞬间就可以传遍整个 P2P 网络。更为恐怖的是,这种攻击是无法停止的,即使是攻击者自身也无法停止,攻击一直持续到 P2P 官方发现问题更新服务器且下载用户重启下载软件为止。 最后总结下,DDoS 不可能防的住,就好比你的店只能容纳 50 人,黑社会有 100 人,你就换一家大店,能容纳 500 人,然后黑社会又找来了 1000 人,这种堆人头的做法就是 DDoS 本质上的攻防之道,「道高一尺,魔高一丈,魔高一尺,道高一丈」,讲真,必要的时候就答应勒索你的人的条件吧,实在不行就报警吧。 流量劫持 流量劫持应该算是黑产行业的一大经济支柱了吧?简直是让人恶心到吐,不吐槽了,还是继续谈干货吧,流量劫持基本分两种:DNS 劫持 和 HTTP 劫持,目的都是一样的,就是当用户访问 zoumiaojiang.com 的时候,给你展示的并不是或者不完全是 zoumiaojiang.com 提供的 “内容”。 DNS 劫持 DNS 劫持,也叫做域名劫持,可以这么理解,「你打了一辆车想去商场吃饭,结果你打的车是小作坊派来的,直接给你拉到小作坊去了」,DNS 的作用是把网络地址域名对应到真实的计算机能够识别的 IP 地址,以便计算机能够进一步通信,传递网址和内容等。如果当用户通过某一个域名访问一个站点的时候,被篡改的 DNS 服务器返回的是一个恶意的钓鱼站点的 IP,用户就被劫持到了恶意钓鱼站点,然后继而会被钓鱼输入各种账号密码信息,泄漏隐私。 dns劫持 这类劫持,要不就是网络运营商搞的鬼,一般小的网络运营商与黑产勾结会劫持 DNS,要不就是电脑中毒,被恶意篡改了路由器的 DNS 配置,基本上做为开发者或站长却是很难察觉的,除非有用户反馈,现在升级版的 DNS 劫持还可以对特定用户、特定区域等使用了用户画像进行筛选用户劫持的办法,另外这类广告显示更加随机更小,一般站长除非用户投诉否则很难觉察到,就算觉察到了取证举报更难。无论如何,如果接到有 DNS 劫持的反馈,一定要做好以下几件事: 取证很重要,时间、地点、IP、拨号账户、截屏、URL 地址等一定要有。 可以跟劫持区域的电信运营商进行投诉反馈。 如果投诉反馈无效,直接去工信部投诉,一般来说会加白你的域名。 HTTP 劫持 HTTP 劫持您可以这么理解,「你打了一辆车想去商场吃饭,结果司机跟你一路给你递小作坊的广告」,HTTP 劫持主要是当用户访问某个站点的时候会经过运营商网络,而不法运营商和黑产勾结能够截获 HTTP 请求返回内容,并且能够篡改内容,然后再返回给用户,从而实现劫持页面,轻则插入小广告,重则直接篡改成钓鱼网站页面骗用户隐私。能够实施流量劫持的根本原因,是 HTTP 协议没有办法对通信对方的身份进行校验以及对数据完整性进行校验。如果能解决这个问题,则流量劫持将无法轻易发生。所以防止 HTTP 劫持的方法只有将内容加密,让劫持者无法破解篡改,这样就可以防止 HTTP 劫持了。 HTTPS 协议就是一种基于 SSL 协议的安全加密网络应用层协议,可以很好的防止 HTTP 劫持。这里有篇 文章 讲的不错。HTTPS 在这就不深讲了,后面有机会我会单独好好讲讲 HTTPS。如果不想站点被 HTTP 劫持,赶紧将你的站点全站改造成 HTTPS 吧。 服务器漏洞 服务器除了以上提到的那些大名鼎鼎的漏洞和臭名昭著的攻击以外,其实还有很多其他的漏洞,往往也很容易被忽视,在这个小节也稍微介绍几种。 越权操作漏洞 如果你的系统是有登录控制的,那就要格外小心了,因为很有可能你的系统越权操作漏洞,越权操作漏洞可以简单的总结为 「A 用户能看到或者操作 B 用户的隐私内容」,如果你的系统中还有权限控制就更加需要小心了。所以每一个请求都需要做 userid 的判断 以下是一段有漏洞的后端示意代码: // ctx 为请求的 context 上下文let msgId = ctx.params.msgId;mysql.query('SELECT FROM msg_table WHERE msg_id = ?',[msgId]); 以上代码是任何人都可以查询到任何用户的消息,只要有 msg_id 就可以,这就是比较典型的越权漏洞,需要如下这么改进一下: // ctx 为请求的 context 上下文let msgId = ctx.params.msgId;let userId = ctx.session.userId; // 从会话中取出当前登陆的 userIdmysql.query('SELECT FROM msg_table WHERE msg_id = ? AND user_id = ?',[msgId, userId]); 嗯,大概就是这个意思,如果有更严格的权限控制,那在每个请求中凡是涉及到数据库的操作都需要先进行严格的验证,并且在设计数据库表的时候需要考虑进 userId 的账号关联以及权限关联。 目录遍历漏洞 目录遍历漏洞指通过在 URL 或参数中构造 …/,./ 和类似的跨父目录字符串的 ASCII 编码、unicode 编码等,完成目录跳转,读取操作系统各个目录下的敏感文件,也可以称作「任意文件读取漏洞」。 目录遍历漏洞原理:程序没有充分过滤用户输入的 …/ 之类的目录跳转符,导致用户可以通过提交目录跳转来遍历服务器上的任意文件。使用多个… 符号,不断向上跳转,最终停留在根 /,通过绝对路径去读取任意文件。 目录遍历漏洞几个示例和测试,一般构造 URL 然后使用浏览器直接访问,或者使用 Web 漏洞扫描工具检测,当然也可以自写程序测试。 http://somehost.com/../../../../../../../../../etc/passwdhttp://somehost.com/some/path?file=../../Windows/system.ini 借助 %00 空字符截断是一个比较经典的攻击手法http://somehost.com/some/path?file=../../Windows/system.ini%00.js 使用了 IIS 的脚本目录来移动目录并执行指令http://somehost.com/scripts/..%5c../Windows/System32/cmd.exe?/c+dir+c:\ 防御 方法就是需要对 URL 或者参数进行 …/,./ 等字符的转义过滤。 物理路径泄漏 物理路径泄露属于低风险等级缺陷,它的危害一般被描述为「攻击者可以利用此漏洞得到信息,来对系统进一步地攻击」,通常都是系统报错 500 的错误信息直接返回到页面可见导致的漏洞。得到物理路径有些时候它能给攻击者带来一些有用的信息,比如说:可以大致了解系统的文件目录结构;可以看出系统所使用的第三方软件;也说不定会得到一个合法的用户名(因为很多人把自己的用户名作为网站的目录名)。 防止这种泄漏的方法就是做好后端程序的出错处理,定制特殊的 500 报错页面。 源码暴露漏洞 和物理路径泄露类似,就是攻击者可以通过请求直接获取到你站点的后端源代码,然后就可以对系统进一步研究攻击。那么导致源代码暴露的原因是什么呢?基本上就是发生在服务器配置上了,服务器可以设置哪些路径的文件才可以被直接访问的,这里给一个 koa 服务起的例子,正常的 koa 服务器可以通过 koa-static 中间件去指定静态资源的目录,好让静态资源可以通过路径的路由访问。比如你的系统源代码目录是这样的: |- project|- src|- static|- ...|- server.js 你想要将 static 的文件夹配成静态资源目录,你应该会在 server.js 做如下配置: const Koa = require('koa');const serve = require('koa-static');const app = new Koa();app.use(serve(__dirname + '/project/static')); 但是如果配错了静态资源的目录,可能就出大事了,比如: // ...app.use(serve(__dirname + '/project')); 这样所有的源代码都可以通过路由访问到了,所有的服务器都提供了静态资源机制,所以在通过服务器配置静态资源目录和路径的时候,一定要注意检验,不然很可能产生漏洞。 最后,希望 Web 开发者们能够管理好自己的代码隐私,注意代码安全问题,比如不要将产品的含有敏感信息的代码放到第三方外部站点或者暴露给外部用户,尤其是前端代码,私钥类似的保密性的东西不要直接输出在代码里或者页面中。也许还有很多值得注意的点,但是归根结底还是绷住安全那根弦,对待每一行代码都要多多推敲。 请关注我的订阅号 本篇文章为转载内容。原文链接:https://blog.csdn.net/MrCoderStack/article/details/88547919。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-01-03 14:51:12
493
转载
JQuery插件下载
...创建和编辑复杂的数学表达式。通过集成该插件,开发者可以轻松实现让用户像在纸上书写一样,在浏览器中输入并预览数学公式的效果。这款插件的一大特色是其交互式的用户界面,用户无需记忆复杂的LaTeX语法,只需点击相应的图标按钮,即可快速插入包括乘方、开方在内的各类数学符号和模板。MathquillBasedEditor不仅提升了用户体验,也极大地简化了数学内容创作者和教育工作者的工作流程,尤其适用于在线教育平台、学术论坛以及各类需要数学公式的Web应用中。 点我下载 文件大小:2.77 MB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2023-07-29 09:21:20
108
本站
VUE
...class属性。根据表达式或计算属性的结果,控制元素上类(class)的添加、移除或更新,实现基于数据状态的条件渲染和样式切换。 计算属性(Computed Properties) , 在Vue.js中,计算属性是一种特殊的属性,它的值依赖于其他响应式属性的值并通过一个getter函数来计算得出。每当依赖的响应式属性变化时,计算属性会自动重新求值并触发相关联视图的更新。例如,在文章中,通过定义isActive计算属性,可以根据数据状态动态决定active class是否应该存在于元素上。 三元表达式(Ternary Operator) , 在编程语言中,三元表达式是条件运算符的一种简写形式,通常写作 condition ? valueIfTrue : valueIfFalse。在Vue的v-bind:class指令使用场景下,三元表达式可以用来简洁地判断某个条件,并据此返回希望绑定到class属性上的字符串。当条件满足时返回一个class名,否则返回空字符串或null以移除对应的class。在文章示例中,someCondition就是一个用于决定 no-class 是否应用到元素上的条件变量。
2023-07-15 17:19:02
197
键盘勇士
HTML
...avaScript 表达式式子,动态组合文本。 // 代码示例 var name = "Tom"; var age = 18; var htmlStr = ${name}的年龄是:${age} ; document.getElementById("content").innerHTML = htmlStr; 采用模板文本会使代码更加清晰简洁。此外,还可以采用第三方库如 Handlebars 或 Mustache 等来实现更为复杂的模板渲染。
2023-11-22 11:28:15
474
电脑达人
Python
...3.8引入了一种新的表达式结构——" walrus operator "(:=),它使得在单行代码中计算列表长度、查找元素索引以及执行条件判断更为简洁高效。此外,对于大数据处理或科学计算场景,NumPy库提供的ndarray对象在性能上远超Python原生列表,可以实现快速的矩阵运算和统计分析。 近期,一篇发布于“Real Python”网站的文章深入探讨了如何利用列表推导式(List Comprehensions)和生成器表达式(Generator Expressions)对列表进行复杂操作,如过滤、映射和压缩数据,从而提升代码可读性和运行效率。文章还介绍了functools模块中的reduce函数,用于对列表元素执行累积操作,如求乘积、求序列中最长连续子序列等。 另外,在实际编程实践中,掌握列表的排序、切片、连接、复制等基本操作同样至关重要。例如,使用sorted()函数或列表的sort()方法对列表进行排序;利用切片技术实现列表的部分提取或替换;通过extend()和+运算符完成列表合并等。这些操作不仅能丰富你对Python列表的理解,更能在日常开发任务中助你事半功倍。 总的来说,深入学习和熟练运用Python列表的各种特性与功能,不仅有助于数据分析和处理,更能提升代码编写质量,使程序更加简洁、高效。同时,关注Python社区的最新动态和最佳实践,将能持续拓展你的编程技能边界,紧跟时代发展步伐。
2023-10-05 18:16:18
359
算法侠
转载文章
...探索编程语言中的条件表达式和逻辑控制的多样性和复杂性。近期,Lua 5.4版本发布,其中对布尔逻辑运算符进行了优化,使得程序员在处理可能为nil的变量时拥有更多选择。例如,新增的andthen与orelse运算符可以更直观地实现“短路求值”,避免了类似原始三目运算符可能导致的问题。 此外,对于条件分支的处理,不仅限于Lua,其他如JavaScript、Python等流行语言也有各自的独特机制和最佳实践。比如,JavaScript引入了Optional Chaining(可选链)语法,允许开发者在访问深层嵌套属性时无需担心因中间路径值为null或undefined而导致程序崩溃。 而在编程范式上,函数式编程强调纯函数和不可变数据结构,其条件表达式的处理方式与命令式编程有所不同,例如Haskell中的Maybe Monad或Elixir中的Pattern Matching机制,都为nil或空值提供了优雅且安全的处理方式。 综上所述,深入研究各种编程语言中条件表达式的设计理念与实现机制,不仅可以帮助我们更好地运用Lua中的特殊写法,还能拓宽视野,提升跨语言编程能力,并在实际项目中实现更为健壮高效的代码逻辑。
2023-12-29 14:47:09
241
转载
Python
...结构,如集合或生成器表达式,在某些场景下能有效避免迭代过程中的状态改变问题。 另外,Python官方文档也强调了对于可变对象在循环中正确操作的重要性,并提供了一系列最佳实践建议。例如,《Effective Python》一书中提到,“在对容器元素进行迭代的同时对其进行修改是一种反模式,应尽量避免”。这一观点与我们之前分析“外星人入侵”游戏bug时得出的结论相吻合,再次提醒我们在实际编程中关注细节,遵循正确的编程范式,以提升代码质量和程序稳定性。
2023-12-10 11:15:11
201
昨夜星辰昨夜风_t
Python
...时或编译期间对变量、表达式或函数参数的数据类型的验证过程。在Python中,尽管其为动态类型语言,但在处理用户输入或其他不确定来源的数据时,进行类型检查是保障代码正确执行的关键步骤。例如,文章中讨论了如何使用isdigit()、isnumeric()和isdecimal()等函数对字符串进行类型检查,判断其是否符合特定数字类型的要求。 input()函数 , 在Python编程中,input()函数用于接收用户的键盘输入,返回值是一个字符串类型。用户可以根据提示在命令行界面或交互式环境中输入文本、数字或其他信息。结合本文内容,当需要检查用户输入是否为数字时,首先调用input()函数获取用户输入并将其作为字符串存储,随后利用Python内置的字符串方法进行进一步的类型检查与验证。
2023-01-16 10:24:29
404
软件工程师
JQuery
...一种机制。通过字符串表达式,开发者可以根据元素的标签名、类名、ID以及其他属性值等特征精确或模糊地选取目标元素。在给出的文章示例中,使用的选择器是input type= text ,这表示选取所有类型为\ text\ 的input元素。通过这种方式,jQuery能获取到需要修改样式的文本框元素,并进一步应用css函数设置其样式属性。
2023-12-10 16:36:43
417
程序媛
JQuery
...函数内部的await表达式,可以显著改善代码的可读性和避免回调地狱问题,这对于编写复杂的插件逻辑至关重要。 近期,Web Components标准也在逐渐成熟,它提倡组件化、封装化的开发模式,并提供了一套原生API支持事件监听和回调机制,这无疑为构建更为模块化、可复用的前端插件带来了新的可能。 同时,对于jQuery插件开发者而言,除了掌握基本的回调函数用法,还需要关注性能优化以及如何更好地融入现代前端生态。例如,通过合理设计API以支持多种类型的回调(如成功回调、失败回调、完成回调等),使插件在各种应用场景下更具通用性与适应力。 综上所述,在持续演进的前端开发领域,理解并有效运用回调机制是提升开发效率和代码质量的关键,而随着技术的发展,回调的应用形式与理念正不断拓展与深化。
2023-09-01 17:58:02
405
逻辑鬼才
AngularJS
...ngsubmit 表达式时,也会抛出错误。 3. 如果我们的 ngsubmit 表达式的返回值不是布尔类型,那么也会出现错误。 如何避免 ngsubmit 表单提交行为异常 使用正确的 AngularJS 版本 首先,确保你在使用的 AngularJS 版本是支持 ngsubmit 的版本。一般来说,较新的 AngularJS 版本都会支持这个特性。 html 使用有效的 ngsubmit 表达式 然后,你需要确保你的 ngsubmit 表达式是有效的。你可以在这个表达式中调用一个方法,该方法会在表单提交前进行数据验证。 html 确保 ngsubmit 表达式的返回值是布尔类型 最后,你需要确保你的 ngsubmit 表达式的返回值是布尔类型。如果你在写表达式的时候,它返回的不是布尔型的结果,那AngularJS就懵圈了,不知道这个时候到底该不该提交表单呢。 html 结论 总的来说,ngsubmit 是一个非常有用的 AngularJS 功能,可以帮助我们在表单提交时执行自定义操作。但是,我们需要小心使用它,以避免出现错误。要是按照上面提到的建议来做,咱们就能稳稳妥妥地绕开这些问题,让咱的应用运行得更加扎实、靠谱。
2023-11-13 22:15:25
463
寂静森林-t
Python
...还具备cron风格的表达式调度,并且兼容多种后台运行模式,如配合Celery进行异步任务队列管理或结合Django等框架实现Web环境下的定时任务调度。 此外,深入探究Python定时任务的实际运用案例,例如NASA就利用Python定时任务技术对其空间站的数据采集系统进行定期维护与更新。通过灵活设定每日、每周甚至每月的任务计划,确保了系统能够按照预设时间点准确无误地完成数据同步及分析工作。 综上所述,在Python中实现高效稳定的定时任务方案,既可以借助如schedule这样的轻量级工具快速搭建原型,也可以根据实际需求选用更为强大的调度库如schedule-ext或APScheduler,从而在不同的业务场景下发挥关键作用。同时,众多现实应用的成功案例也证明了Python定时任务功能在各行业自动化流程中的重要价值。
2023-01-01 19:28:30
351
软件工程师
Java
...运算符仅仅是众多逻辑表达式工具的两个代表。实际上,在现代软件开发中,尤其是面对复杂业务逻辑和高效算法设计时,深入理解和熟练运用逻辑运算符是必不可少的技能。 最近的一则新闻报道显示,Google在优化其Android系统性能的过程中,工程师们就巧妙利用了逻辑运算符的短路特性(Short-Circuit Evaluation),在某些条件检查场景下显著提升了代码执行效率。他们通过合理组织if语句中的逻辑表达式顺序,使得在满足特定条件时,无需计算后续复杂的或不必要的逻辑分支,从而减少CPU资源消耗,提升用户体验。 此外,对于初学者或者进阶开发者来说,理解逻辑运算符在并发编程、函数式编程以及数据库查询语句中的应用也非常重要。例如,在多线程环境下的锁机制实现时,常常会用到逻辑与(&&)来确保多个条件同时满足才进行特定操作,以避免竞态条件的发生;而在SQL查询中,WHERE子句中的AND、OR等逻辑运算符则是构建复杂查询的基础元素。 更进一步,逻辑运算符不仅仅局限于二元操作,还有诸如三元运算符(Ternary Operator)和逻辑非(Not Operator)等形式,它们在简化代码结构、增强可读性方面同样发挥着不可忽视的作用。因此,持续探索和实践逻辑运算符在不同编程场景下的应用,将有助于我们编写出更加精炼、高效且易于维护的代码。
2024-02-21 16:05:44
275
码农
JSON
...r则凭借其强大的模板表达式和变更检测系统,让JSON数据操作变得直观高效。 此外,在Node.js后端环境中,诸如Express框架支持直接将JSON传递给路由处理器,并内建了中间件来解析JSON请求体。同时,使用诸如axios或fetch这类现代HTTP客户端库,可以更加优雅地发起异步请求并处理返回的JSON数据。 近期,ECMAScript标准也在JSON支持上进行了优化,如引入JSON.stringify()的第三个参数用于定制化序列化过程,以及JSON.parse()可选的reviver函数对反序列化结果进行深度处理。这些新特性的运用能够帮助开发者更精细地控制JSON数据在程序中的流转和表现形式。 总的来说,理解并熟练掌握JSON数据处理已经成为现代全栈开发者的必备技能,持续关注相关技术和最佳实践的发展,能更好地适应快速变化的Web开发环境,提升开发效率和代码质量。
2023-07-24 23:16:09
441
逻辑鬼才
HTML
...候我们需要将一些算式表达或者其他的运算结果呈现在网页上。当然,在 HTML 中,我们也可以直接运用一些数学标记,例如“√”、“π”等等。 不过,在一些复杂的计算中,运用标记明显是不够的,我们需要运用一些特殊的手段去计算这些公式。幸运的是,HTML 中也提供了这样的手段,我们可以借助在程序内运用一些预先设定的公式来执行计算。 <!-- 数学运算 --> <p>计算圆的圆周:C = 2πr</p> 在上面的程序内,我们运用了圆的圆周公式来呈现如何在 HTML 中计算公式。其中,“π”是一个已经预先设定好的数学标记,我们可以直接在程序内运用它。 <!-- 数学运算 --> <p>计算正方形的面积大小:A = a²</p> 同样地,在上面的程序内,我们运用了正方形面积大小的公式来执行计算。其中,“²”也是一个已经预先设定好的数学标记,它表示的是平方。 除了这些预先设定的数学标记之外,我们还可以运用一些特殊的代码来执行更加复杂的计算。例如,在下面的例子中,我们运用了一些特殊的代码来计算三角形的面积大小: <!-- 数学运算 --> <p>计算三角形的面积大小:A = ½bh</p> 在上面的程序内,“½”就是一个特殊的代码,表示的是除以二。同理,我们还可以运用“⅓”、“¼”等等来执行更加复杂的计算。 总之,数学运算在 HTML 中是非常重要的。借助运用预先设定的数学标记和特殊的代码,我们可以方便地执行复杂的计算,从而更加简便地创作出高质量的网页。
2023-04-01 16:00:57
321
电脑达人
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
nohup command &
- 在后台运行命令且在退出终端后仍继续运行。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"