goahead源码分析webs.c

webs.cweb层)

Web层主要功能是处理http协议,处理web服务器业务。可以说是整个web服务器的重点。

对于其的详细分析,以后再写。

一个基本认证例子的消息头:

请求。

POST /goform/cfgSdhifRsWeb HTTP/1.1

Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*

Referer: http://192.168.4.28/sdhifrs.asp?slot=0

Accept-Language: zh-cn

User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727)

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

Host: 192.168.4.28

Content-Length: 137

Proxy-Connection: Keep-Alive

Pragma: no-cache

Authorization: Basic cmFpc2Vjb206cmFpc2Vjb20=

 

portIndex=1&exc=3&sd=6&es=900&ses=900&msais_insert=2&j0_mode=2&j0_transmit=Raisecom-Opcom+&j0_expected=Raisecom-Opcom+&slot=0&apply=Apply

 

响应。

HTTP/1.0 302 Redirect

Server: Webs/2.5.0

Date: THU JAN 01 00:06:48 1970

Pragma: no-cache

Cache-Control: no-cache

Content-Type: text/html

Location: http://192.168.4.28/sdhifrs.asp?slot=0&&portIndex=1

 

<html><head></head><body>

        This document has moved to a new <a href="http://192.168.4.28/sdhifrs.asp?slot=0&&portIndex=1">location</a>.

        Please update your documents to reflect the new location.

        </body></html>

 

 

一个摘要认证例子的消息头:

 

请求。

POST /goform/cfgSdhifRsWeb HTTP/1.1

Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*

Referer: http://192.168.4.28/sdhifrs.asp?slot=0&&portIndex=1

Accept-Language: zh-cn

User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727)

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

Host: 192.168.4.28

Content-Length: 137

Proxy-Connection: Keep-Alive

Pragma: no-cache

Authorization: Digest username="123",realm="123",nonce="0fabdfd5b279fadc2f0d9d72ed218c29",uri="/goform/cfgSdhifRsWeb",cnonce="e5003c43b0ba085d63cd1e92021c6ecc",nc=00000019,algorithm=MD5,response="a97274a2c9d6e8ccbb7e9200c1bc4e56",qop="auth",opaque="5ccc069c403ebaf9f0171e9517f40e41"

 

portIndex=1&exc=3&sd=6&es=900&ses=900&msais_insert=2&j0_mode=2&j0_transmit=Raisecom-Opcom+&j0_expected=Raisecom-Opcom+&slot=0&apply=Apply

 

响应。

HTTP/1.0 302 Redirect

Server: Webs/2.5.0

Date: THU JAN 01 00:01:54 1970

Pragma: no-cache

Cache-Control: no-cache

Content-Type: text/html

Location: http://192.168.4.28/sdhifrs.asp?slot=0&&portIndex=1

 

<html><head></head><body>

        This document has moved to a new <a href="http://192.168.4.28/sdhifrs.asp?slot=0&&portIndex=1">location</a>.

        Please update your documents to reflect the new location.

        </body></html>

 

 

 

HTTP Keep-Alive

Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。市场上 的大部分Web服务器,包括iPlanet、IIS和Apache,都支持HTTP Keep-Alive。对于提供静态内容的网站来说,这个功能通常很有用。但是,对于负担较重的网站来说,这里存在另外一个问题:虽然为客户保留打开的连 接有一定的好处,但它同样影响了性能,因为在处理暂停期间,本来可以释放的资源仍旧被占用。当Web服务器和应用服务器在同一台机器上运行时,Keep- Alive功能对资源利用的影响尤其突出。 此功能为HTTP 1.1预设的功能,HTTP 1.0加上Keep-Alive header也可以提供HTTP的持续作用功能。

Keep-Alive: timeout=5, max=100
timeout:过期时间5秒(对应httpd.conf里的参数是:KeepAliveTimeout),max是最多一百次请求,强制断掉连接

就是在timeout时间内又有新的连接过来,同时max会自动减1,直到为0,强制断掉。

 

 

If-Modified-Since

 

If-Modified-Since是标准的HTTP请求头标签,在发送HTTP请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。

如果时间一致,那么返回HTTP状态码304(不返回文件内容),客户端接到之后,就直接把本地缓存文件显示到浏览器中。

如果时间不一致,就返回HTTP状态码200和新的文件内容,客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示到浏览器中。

HTTP的If-Modified-Since头标签与客户端缓存相互配合,大大节约了网络流量。

 

HTTP的认证模式

 

Http协议(RFC 2616 )规定可以采用Base模式和摘要模式(Digest schema)。RFC 2617 专门对两种认证模式做了规定。RFC 1321 是MD5标准。Digest对现代密码破解来说并不强壮,但比基本模式还是好很多。MD5已经被山东大学教授找到方法可以仿冒(我的理解),但现在还在广泛使用。

1.最简单的攻击方式

  如果网站要求认证,客户端发送明文的用户名密码,那网络上的窃听者可以轻而易举的获得用户名密码,起不到安全作用。我上学时曾在科大实验室局域网内窃听别人的科大BBS的密码,发现BBS的用户名密码居然是明文传输的。那种做贼的心虚和做贼的兴奋让人激动莫名。偷人钱财会受到道德谴责,偷人密码只会暗自得意忘形。比“窃书不算偷”还没有罪恶感。因此你的用户名和密码明文传输的话,无异将一块肥肉放在嘴馋的人面前。现在很多ASP网站的认证都将用户名和密码用MD5加密。MD5是将任意长度的字符串和128位的随机数字运算后生成一个16byte的加密字符串。因此窃听者抓住的是一团乱码。但是,这有一个问题:如果窃听者就用这团乱码去认证,还是可以认证通过。因为服务器将用户名密码MD5加密后得到的字符串就是那一团乱码,自然不能区别谁是合法用户。这叫重放攻击(replay attack)。这和HTTP的基本认证模式差不多。为了安全,不要让别人不劳而获,自然要做基本的防范。下面是Http协议规定的两种认证模式。

2.基本认证模式

  客户向服务器发送请求,服务器返回401(未授权),要求认证。401消息的头里面带了挑战信息。realm用以区分要不同认证的部分。客户端收到401后,将用户名密码和挑战信息用BASE64加密形成证书,发送回服务器认证。语法如下:

      challenge   = "Basic" realm
      credentials = "Basic" basic-credentials

示例:

   认证头: WWW-Authenticate: Basic realm="zhouhh@mydomain.com"
   
证书:Authorization: Basic QsdfgWGHffuIcaNlc2FtZQ==


3.摘要访问认证

  为了防止重放攻击,采用摘要访问认证。在客户发送请求后,收到一个401(未授权)消息,包含一个Challenge。消息里面有一个唯一的字符串:nonce,每次请求都不一样。客户将用户名密码和401消息返回的挑战一起加密后传给服务器。这样即使有窃听,他也无法通过每次认证,不能重放攻击。Http并不是一个安全的协议。其内容都是明文传输。因此不要指望Http有多安全。

语法:

      challenge        =  "Digest" digest-challenge

      digest-challenge  = 1#( realm | [ domain ] | nonce |
                          [ opaque ] |[ stale ] | [ algorithm ] |
                          [ qop-options ] | [auth-param] )


      domain            = "domain" "=" <"> URI ( 1*SP URI ) <">
      URI               = absoluteURI | abs_path
      nonce             = "nonce" "=" nonce-value
      nonce-value       = quoted-string
      opaque            = "opaque" "=" quoted-string
      stale             = "stale" "=" ( "true" | "false" )
      algorithm         = "algorithm" "=" ( "MD5" | "MD5-sess" |
                           token )
      qop-options       = "qop" "=" <"> 1#qop-value <">
      qop-value         = "auth" | "auth-int" | token


realm:让客户知道使用哪个用户名和密码的字符串。不同的领域可能密码不一样。至少告诉用户是什么主机做认证,他可能会提示用哪个用户名登录,类似一个Email。
domain:一个URI列表,指示要保护的域。可能是一个列表。提示用户这些URI采用一样的认证。如果为空或忽略则为整个服务器。
nonce:随机字符串,每次401都不一样。跟算法有关。算法类似Base64加密:time-stamp H(time-stamp ":" ETag ":" private-key) 。time-stamp为服务器时钟,ETag为请求的Etag头。private-key为服务器知道的一个值。
opaque:服务器产生的由客户下去请求时原样返回。最好是Base64串或十六进制字符串。
auth-param:为扩展用的,现阶段忽略。
其他域请参考RFC2617。

授权头语法:

       credentials      = "Digest" digest-response
       digest-response  = 1#( username | realm | nonce | digest-uri
                       | response | [ algorithm ] | [cnonce] |
                       [opaque] | [message-qop] |
                           [nonce-count]  | [auth-param] )

       username         = "username" "=" username-value
       username-value   = quoted-string
       digest-uri       = "uri" "=" digest-uri-value
       digest-uri-value = request-uri   ; As specified by HTTP/1.1
       message-qop      = "qop" "=" qop-value
       cnonce           = "cnonce" "=" cnonce-value
       cnonce-value     = nonce-value
       nonce-count      = "nc" "=" nc-value
       nc-value         = 8LHEX
       response         = "response" "=" request-digest
       request-digest = <"> 32LHEX <">
       LHEX             =  "0" | "1" | "2" | "3" |
                           "4" | "5" | "6" | "7" |
                           "8" | "9" | "a" | "b" |
                           "c" | "d" | "e" | "f"

response:加密后的密码
digest-uri:拷贝Request-Line,用于Proxy
cnonce:如果qop设置,才设置,用于双向认证,防止攻击。
nonce-count:如果服务器看到同样的计数,就是一次重放。

示例:

401响应:        HTTP/1.1 401 Unauthorized
         WWW-Authenticate: Digest
                 realm="
testrealm@host.com",
                 qop="auth,auth-int",
                 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                 opaque="5ccc069c403ebaf9f0171e9517f40e41"
再次请求:
         Authorization: Digest username="Mufasa",
                 realm="
testrealm@host.com",
                 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
                 uri="/dir/index.html",
                 qop=auth,
                 nc=00000001,
                 cnonce="0a4f113b",
                 response="6629fae49393a05397450978507c4ef1",
                 opaque="5ccc069c403ebaf9f0171e9517f40e41"

4.比较基本认证和摘要访问认证都是很脆弱的。基本认证可以让窃听者直接获得用户名和密码,而摘要访问认证窃听者只能获得一次请求的文档。

 

int websOpenServer(int port, int retries)

功能:打开web服务器,打开rom,创建mime table,打开url处理模块打开form 模块,打开监听socket

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websCloseServer()

功能:关闭web服务器,关闭监听socket,关闭已经连接的socket

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websOpenListen(int port, int retries)

功能:打开监听socket

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websCloseListen()

功能:关闭监听socket

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websAccept(int sid, char *ipaddr, int port, int listenSid)

功能:接收一个连接,创建钩子函数websSocketEvent,对应于该socket可读,设置该socket挂起请求的超时处理函数websTimeout

说明:

-----------------------------------------------------------------------------------------------------------------

 

static void websSocketEvent(int sid, int mask, void* iwp)

功能:响应读写操作

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websReadEvent(webs_t wp)

功能:读操作响应函数,是web服务器读取从浏览器发来的数据,读取数据是分阶段的,WEBS_BEGINWEBS_HEADERWEBS_POST_CLENWEBS_POST

说明:

-----------------------------------------------------------------------------------------------------------------

 

static int websGetInput(webs_t wp, char_t **ptext, int *pnbytes)

功能:从浏览器获取数据

说明:

-----------------------------------------------------------------------------------------------------------------

 

static int websParseFirst(webs_t wp, char_t *text)

功能:分析http请求的第一行

说明:

-----------------------------------------------------------------------------------------------------------------

 

static void websParseRequest(webs_t wp)

功能:分析head全部请求

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websSetEnv(webs_t wp)

功能:设置环境变量

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websSetVar(webs_t wp, char_t *var, char_t *value)

功能:设置web变量

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websTestVar(webs_t wp, char_t *var)

功能:测试这个cgi 变量是否存在

说明:

-----------------------------------------------------------------------------------------------------------------

 

char_t *websGetVar(webs_t wp, char_t *var, char_t *defaultGetValue)

功能:获取web的变量,主要是post的表单数据或query数据

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websCompareVar(webs_t wp, char_t *var, char_t *value)

功能:是否这个web变量

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websTimeoutCancel(webs_t wp)

功能:超时处理取消函数

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websResponse(webs_t wp, int code, char_t *message, char_t *redirect)

功能:向浏览器输出web服务器的响应

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websRedirect(webs_t wp, char_t *url)

功能:web重定向,定位到另一个页面

说明:

-----------------------------------------------------------------------------------------------------------------

 

static int charCount(const char_t* str, char_t ch)

功能:统计字符ch在字符串str中出现的次数

说明:

-----------------------------------------------------------------------------------------------------------------

 

static char_t* websSafeUrl(const char_t* url)

功能:主要是将<>字符转换为&lt;&gt;

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websError(webs_t wp, int code, char_t *fmt, ...)

功能:向浏览器输出错误

说明:

-----------------------------------------------------------------------------------------------------------------

 

char_t *websErrorMsg(int code)

功能:根据错误码输出对应的解释性字符

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websWrite(webs_t wp, char_t *fmt, ...)

功能:向浏览器输出字符串

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websWriteBlock(webs_t wp, char_t *buf, int nChars)

功能:向浏览器一段数据

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websWriteDataNonBlock(webs_t wp, char *buf, int nChars)

功能:向浏览器一段数据

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websDecodeUrl(char_t *decoded, char_t *token, int len)

功能:url解码函数,主要是将+%xx等解码成空格、字符

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websTimeout(void *arg, int id)

功能:超时处理函数,如果超时,则释放内存,向浏览器输出结果,如果还未超时,重新启动定时函数,定时的时间为剩余的时间

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websDone(webs_t wp, int code)

功能:一个请求处理完成的结束函数,向浏览器输出数据,释放内存

说明:

-----------------------------------------------------------------------------------------------------------------

 

int websAlloc(int sid)

功能:分配一个webs_t结构

说明:

-----------------------------------------------------------------------------------------------------------------

 

void websFree(webs_t wp)

功能:?

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值