A. 如何在伺服器端判斷請求的客戶端是微信調用的瀏覽器
php代碼
public function is_weixin(){
if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false ) {
return true;
}
return false;
}
if($this->is_weixin()){
}else{
echo "請使用微信訪問本網址。";
}
在iPhone下
Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176 MicroMessenger/4.3.2
在Android下
Mozilla/5.0 (linux; U; Android 2.3.6; zh-cn; GT-S5660 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MicroMessenger/4.5.255
包含「MicroMessenger」可以判斷為微信瀏覽器,順便不僅可以看到是什麼手機、微信版本還有其他更多的東西。
B. 伺服器,如何判斷一個http請求是來自瀏覽器還是其他終端
原理和實現方法如下:
1、手機訪問網站時時,會附帶發送user-agent信息,這個信息裡面會有手機號碼信息,則可以肯定是通過手機wap訪問的。
2、但是目前中 國移動已經屏蔽了user-agent信息,所以獲取不到手機號碼。可以把wap網站伺服器的ip提交給中國移動,加入白名單 後即可取得ua信息。目前中國聯通可以直接取到手機號,對聯通用戶此方案可完美實施。
3、手機訪問,原理是手機通過移動公司的代理伺服器進行的訪問。那麼就可以理解是一台普通電腦使用了代理伺服器。當手機通過代理伺服器訪問的時候,http頭信息會毫無疑問的包含一個信息:via。這個信息提供了有價值的判斷信息。可以實現判斷是否是移動終端。
4、另外現在移動端的瀏覽器都會請求移動版的網頁,所以可以直接判斷出的。
C. 伺服器如何判斷post請求者身份
一般有兩種方法,一種傳統的用cookie
另一種是通過token的方式,就是你說的那種
referer的方式不可行,只要用戶可以修改的數據都不可信,而token是用戶登錄後服務端下發的,原則上客戶端不能自己生成,所以可以驗證身份
D. 伺服器,怎麼判斷一個http請求是來自瀏覽器
1、如伺服器提供了web服務,則通過伺服器本身的web平台查看會話記錄;
2、通過本機的防火牆軟體查當前會話情況(主要看協議);
3、netstat -an 查看分析;
4、抓包軟體查看會話(例如wireshark).
以上各種方法都可以
E. 伺服器如何判別用戶請求的設備為iOS還是Android設備還是windows...
通過 Agent 來判斷相應的智能手機設備,然後跳轉到新的手機站點
經過不懈的努力,終於搜集了比較全的 智能設備 的 Agent,然後又寫了程序,直接上代碼吧,希望能幫助到你
Js代碼
/// 根據 Agent 判斷是否是智能手機
///</summary>
///<returns></returns>
public static bool CheckAgent()
{
bool flag = false;
string agent = HttpContext.Current.Request.UserAgent;
string[] keywords = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };
//排除 Windows 桌面系統
if (!agent.Contains("Windows NT") || (agent.Contains("Windows NT") && agent.Contains("compatible; MSIE 9.0;")))
{
//排除 蘋果桌面系統
if (!agent.Contains("Windows NT") && !agent.Contains("Macintosh"))
{
foreach (string item in keywords)
{
if (agent.Contains(item))
{
flag = true;
break;
}
}
}
}
return flag;
}
F. 伺服器端如何判斷ajax請求方式
你指的請求方式是指GET、POST、HEAD、OPTIONS、PUT、DELETE、TRACE、CONNECT么?
那麼分析http頭就能看到了
get方式:
G. 伺服器端如何判斷是請求是通過手機還是PC發出的
看IP,手機上網的IP段都是固定的,所以說一般是通過IP的。而往往很多的手機上網IP都是一樣的,不想電腦一樣。
H. 伺服器怎麼用時間驗證http請求
問題簡化一下:對一個ip,一個線程請求100次。該次請求的響應時間為調用httpClient前的響應時間減去接收到httpClient響應的時間。注意,本次請求是否有效要判斷。平均響應時間和最大響應時間只不過是響應時間的統計而已,可以用資料庫來做。
就是說資料庫記錄每次測試請求的響應時間,成功與否。統計數據最後出來。
只所以用多線程,是因為單線程順序請求100次,不能模擬伺服器真正的情況。
I. 如何判斷HTTP請求來源的正確性
在jquery框架中,對於通過它的$.ajax, $.get, or $.post方法請求網頁內容時,它會向伺服器傳遞一個HTTP_X_REQUESTED_WITH的參數,你可以利用如下方法判斷某個請 求是ajax請求還是普通請求 if ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ) { //ajax request } else { // not ajax request } 在使用原生 JavaScript 發出 ajax 請求時,我們也可以給頭部添加信息,以方便後端同學進行區分,方法如下: 1 var xmlhttp=new XMLHttpRequest(); 2 xmlhttp.open("GET","test.php",true); 3 xmlhttp.setRequestHeader("X-Requested-With","XMLHttpRequest"); 4 xmlhttp.send();
J. linux伺服器如何感知有connect請求
1、sys_connect
對於客戶端來說,當創建了一個套接字後,就可以連接它了。
case SYS_CONNECT:
err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
break;[/code]
asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
{
struct socket *sock;
char address[MAX_SOCK_ADDR];
int err;
sock = sockfd_lookup(fd, &err);
if (!sock)
goto out;
err = move_addr_to_kernel(uservaddr, addrlen, address);
if (err < 0)
goto out_put;
err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
if (err) goto out_put;
err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
sock->file->f_flags);
out_put:
sockfd_put(sock);
out:
return err;
}
跟其它操作類似,sys_connect 接著調用 inet_connect:
/*
* Connect to a remote host. There is regrettably still a little
* TCP 'magic' in here.
*/
int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
struct sock *sk = sock->sk;
int err;
long timeo;
lock_sock(sk);
if (uaddr->sa_family == AF_UNSPEC) {
err = sk->sk_prot->disconnect(sk, flags);
sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
goto out;
}
提交的協議簇不正確,則斷開連接。
switch (sock->state) {
default:
err = -EINVAL;
goto out;
case SS_CONNECTED:
err = -EISCONN;
goto out;
case SS_CONNECTING:
err = -EALREADY;
/* Fall out of switch with err, set for this state */
break;[/code] socket 處於不正確的連接狀態,返回相應的錯誤值。
case SS_UNCONNECTED:
err = -EISCONN;
if (sk->sk_state != TCP_CLOSE)
goto out;
/*調用協議的連接函數*/
err = sk->sk_prot->connect(sk, uaddr, addr_len);
if (err < 0)
goto out;
/*協議方面的工作已經處理完成了,但是自己的一切工作還沒有完成,所以切換至正在連接中*/
sock->state = SS_CONNECTING;
/* Just entered SS_CONNECTING state; the only
* difference is that return value in non-blocking
* case is EINPROGRESS, rather than EALREADY.
*/
err = -EINPROGRESS;
break;
}
對於 TCP的實際的連接,是通過調用 tcp_v4_connect()函數來實現的。
二、tcp_v4_connect函數
對於 TCP 協議來說,其連接,實際上就是發送一個 SYN 報文,在伺服器的應到到來時,回答它一個 ack 報文,也就是完成三次握手中的第一和第三次。
要發送 SYN 報文,也就是說,需要有完整的來源/目的地址,來源/目的埠,目的地址/埠由用戶態提交,但是問題是沒有自己的地址和埠,因為並沒有調 用過 bind(2),一台主機,對於埠,可以像 sys_bind()那樣,從本地未用埠中動態分配一個,那地址呢?因為一台主機可能會存在多個 IP地 址,如果隨機動態選擇,那麼有可能選擇一個錯誤的來源地址,將不能正確地到達目的地址。換句話說,來源地址的選擇,是與路由相關的。
調用路由查找的核心函數 ip_route_output_slow(),在沒有提供來源地址的情況下,會根據實際情況,調用 inet_select_addr()函數來選擇一個合適的。同時,如果路由查找命中,會生成一個相應的路由緩存項,這個緩存項,不但對當前發送 SYN 報 文有意義,對於後續的所有數據包,都可以起到一個加速路由查找的作用。這一任務,是通過 ip_route_connect()函數完成的,它返回相應的路由緩存項(也就是說,來源地址也在其中了):
static inline int ip_route_connect(struct rtable **rp, u32 dst,
u32 src, u32 tos, int oif, u8 protocol,
u16 sport, u16 dport, struct sock *sk)
{ struct flowi fl = { .oif = oif,
.nl_u = { .ip4_u = { .daddr = dst,
.saddr = src,
.tos = tos } },
.proto = protocol,
.uli_u = { .ports =
{ .sport = sport,
.dport = dport } } };
int err;
if (!dst || !src) {
err = __ip_route_output_key(rp, &fl);
if (err)
return err;
fl.fl4_dst = (*rp)->rt_dst;
fl.fl4_src = (*rp)->rt_src;
ip_rt_put(*rp);
*rp = NULL;
}
return ip_route_output_flow(rp, &fl, sk, 0);
}
首先,構建一個搜索 key fl,在搜索要素中,來源地址/埠是不存在的。所以,當通過__ip_route_output_key 進行查找時,第一次是不會命中緩存的。 __ip_route_output_key 將繼續調用ip_route_output_slow()函數,在路由表中搜索,並返回一個合適的來源地址, 並且生成一個路由緩存項。 路由查找的更多細節,我會在另一個貼子中來分析。
/* This will initiate an outgoing connection. */
int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
struct rtable *rt;
u32 daddr, nexthop;
int tmp;
int err;
if (addr_len < sizeof(struct sockaddr_in))
return -EINVAL;
if (usin->sin_family != AF_INET)
return -EAFNOSUPPORT;
校驗地址長度和協議簇。
nexthop = daddr = usin->sin_addr.s_addr;
將下一跳地址和目的地址的臨時變數都暫時設為用戶提交的地址。
if (inet->opt && inet->opt->srr) {
if (!daddr)
return -EINVAL;
nexthop = inet->opt->faddr;
}
如果使用了來源地址路由,選擇一個合適的下一跳地址。
tmp = ip_route_connect(&rt, nexthop, inet->saddr,
RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
IPPROTO_TCP,
inet->sport, usin->sin_port, sk);
if (tmp < 0)
return tmp;
if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
ip_rt_put(rt);
return -ENETUNREACH;
}
進行路由查找,並校驗返回的路由的類型,TCP是不被允許使用多播和廣播的。
if (!inet->opt || !inet->opt->srr)
daddr = rt->rt_dst;
更新目的地址臨時變數——使用路由查找後返回的值。
if (!inet->saddr)
inet->saddr = rt->rt_src;
inet->rcv_saddr = inet->saddr;
如果還沒有設置源地址,和本地發送地址,則使用路由中返回的值。
if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {
/* Reset inherited state */
tp->rx_opt.ts_recent = 0;
tp->rx_opt.ts_recent_stamp = 0;
tp->write_seq = 0;
}
if (sysctl_tcp_tw_recycle &&
!tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
struct inet_peer *peer = rt_get_peer(rt);
/* VJ's idea. We save last timestamp seen from
* the destination in peer table, when entering state TIME-WAIT
* and initialize rx_opt.ts_recent from it, when trying new connection.
*/
if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
tp->rx_opt.ts_recent = peer->tcp_ts;
}
}
這個更新初始狀態方面的內容,還沒有去分析它。
inet->dport = usin->sin_port;
inet->daddr = daddr;
保存目的地址及埠。
tp->ext_header_len = 0;
if (inet->opt)
tp->ext_header_len = inet->opt->optlen;
tp->rx_opt.mss_clamp = 536;
設置最小允許的 mss 值
tcp_set_state(sk, TCP_SYN_SENT);
套接字狀態被置為 TCP_SYN_SENT,
err = tcp_v4_hash_connect(sk);
if (err)
goto failure;
動態選擇一個本地埠,並加入 hash 表,與bind(2)選擇埠類似。
err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
if (err)
goto failure;
/* OK, now commit destination to socket. */
__sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst);
因為本地埠已經改變,使用新埠,重新查找路由,並用新的路由緩存項更新 sk 中保存的路由緩存項。
if (!tp->write_seq)
tp->write_seq = secure_tcp_sequence_number(inet->saddr,
inet->daddr,
inet->sport,
usin->sin_port);
為 TCP報文計算一個 seq值(實際使用的值是 tp->write_seq+1)。
inet->id = tp->write_seq ^ jiffies;
err = tcp_connect(sk);
rt = NULL;
if (err)
goto failure;
return 0;
tp_connect()函數用來根據 sk 中的信息,構建一個完成的 syn 報文,並將它發送出去。在分析 tcp棧的實現時再來分析它。
根據 TCP協議,接下來的問題是,
1、可能收到了伺服器的應答,則要回送一個 ack 報文;
2、如果超時還沒有應答,則使用超時重發定時器;