菜单

何以选择Python的Requests包实现模拟登陆

2019年3月25日 - 金沙编程资讯

image

那种状态是多多益善偷懒的程序员或然傻X的高管接纳的点子,因为做起来实在太快。如果自个儿网站是响应式布局,那么很有或许不需求做什么样改变,就假诺在支付时打开始页就好了,那样Hybird的APP外壳就纯粹成为了二个浏览器。
但比起这么做带来的重重通病来,开发进程快的优点大致能够忽略不计。
率先,在互连网环境倒霉时,纯大白页,用户体验0;
然后,CSS和JS等能源不在本地,供给长途载入,假设使用了bootstrap之类的框架,那用户为了开一下APP而消耗的流量真是让人感动;
再然后,网页里常用的jquery,在手机的webview里速度并不可能,而一旦是非ajax的网页那就更闹心了,每趟操作都要跳转和页面渲染,要令人把它当成APP那实在是嘲谑。
再再然后,那样的所谓APP,要透过Appstore的甄别,那是痴心妄想的(除非审核员当天闹肚子严重,拿着纸巾奔向厕所前误点了通过……),苹果的渴求是,那得是APP,而不能够是有个别网站做成APP的金科玉律,那样的景观相符做Web
APP。而据小编所知,国内几个较大的Android市镇,那样的APP也是不能够通过审查批准的。

4.1.询问播放地址

{
    "code": 0,
    "data": {
        "count": 1,
        "items": [
            {
                "id": 104,
                "resource_id": 39,
                "web_url": "/mp4/vod/yellowstone/yellowstone.mp4",
                "web_io_protocol": "http-mp4",
                "add_time": "2017-08-25 16:35:16"
            }
        ]
    }
}

重返0个或多少个广播地址,一个能源大概有多少个区别协商的播报地址。
resource_id 财富编号
web_url 播出地址
“web_io_protocol 播出协议

代码看起来好像平昔不什么样难题。但是执行的时候出错了。核对了一晃,错误的来头是,csrf验证失败!

图片 1

程序员总能给自个儿找到偷懒的章程,有的程序为了省事,会在用户登录后,直接把用户名和密码保存在本地,然后每趟调用后端接口时作为参数字传送递。真省事儿啊!可那种艺术简单易行就像拿着一袋子钱在旅途边走边喊“快来抢作者哟!快来抢作者哟!”,二个非常的小的嗅探器就能把用户的密码得到手,假使用户习惯在有着地方用一个密码,那么你闯大祸了,黑客通过撞库的主意能把用户的富有消息一锅端。

2.2.询问分类树

{
    "code": 0,
    "data": {
        "count": 2,
        "items": [
            {
                "id": 1,
                "name": "公共栏目",
                "comment": "",
                "upper_catalog_id": 0,
                "sub_items": [
                                {
                                    "id": 5,
                                    "name": "二级分类1",
                                    "comment": "",
                                    "upper_catalog_id": 1
                                },
                                ...
                    ]
            },
            ...
        ]
    }
}

id 编号
name 名称
comment 备注
“upper_catalog_id 上级分类编号, 0 表示近日分类是一级分类。
sub_items 下级分类数组,包罗 0 或多少个下级分类。

再反复肯定获得的csrf和请求登录的csrf字符串没难题了之后,作者想到了一个题材。
一旦,大家还不知情不当原因来说,那里能够暂停思考三个问题。“服务器怎样精通,第一次呼吁获取csrf和第一回post登录请求是同七个用户?”

图片 2

你是或不是真正要求登录功能?
把那几个标题放在最前方并不是灌水,而是真的见过很多并不要求登录的APP去做了登录功效,可能是并不需求强制登录的APP把登录作为运转页。
用户对你的APP一窍不通,你就须求对方注册并登录,除非APP本身已经很有声望恐怕是用户有强供给,不然符合规律人应有会一贯把它删掉。
比较温柔的法门是将一部分并不要求登录,但足以给用户带来援助的东西,第权且间突显给她们,让她们产生兴趣,再在适度的机遇引导他们注册(比如利用要求使用更高级的功力,或用户须要收藏有个别喜欢的音讯时)。

5.4.logout

{
    "code": 0,
}

里面csrf是为了以免万一跨域脚本伪造。原理很不难,就是每1次呼吁,服务器生成一串加密字符串。放在隐藏的input表单中。再二回呼吁的时候,把这么些字符串一起传过去,为了印证是不是为同一个用户的伸手。

二 、输入用户名密码后:

还记得刚才APP向服务器请求token时,能够插足的用户音讯吗?比如用户的装置deviceid。
假如咱们在调用接口时,还捎带2个当下时间戳参数timestamp,同时,用deviceid和这些时刻戳再生成叁个参数sign,比如
md5(deviceid timestamp
token)那样的样式。而服务端首先验证一下参数中的时间戳与当下服务器时间是还是不是相同(误差保持在合理范围内即可,比如六分钟),然后依照用户保存在服务器中的deviceid来对参数中的时间戳举行相同的变形,验证是或不是同盟,那便自然“更更安全”了。
tips:借使对一切调用请求中的参数进行排序,再以deviceid和timestamp加上排序后的参数来对全部调用生成三个sign,黑客正是截获sign,区别的时间点、参数请求所使用的sign也是例外的,难以伪造,自然会更安全。当然,写起来也更麻烦。
tips:驾驭了规律,整个验证进程是足以依照本人的急需改造的。

1.概述

所以大家的代码,必要在率先次呼吁的时候获得这些sessionID。第二遍呼吁的时候把这些sessionID一起传过去。而requests厉害的地点就是,一句简单requests.Session(),就能动用那一个会话对象。

image

//检查是或不是已报到
UserInfo.has_login = function(){
    var username = UserInfo.username();
    var pwd = UserInfo.password();
    var token = UserInfo.token();
    if(!username || !pwd || !token){
        return false;
    }
    return true;
};

2.询问分类

首先份代码

图片 3

还要更更安全(那标题真方便)

5.3.login2

{
    "code": 0,
    "data": {
        "count": 6,
        "items": [{
            "id": 2,
            "name": "王工",
            "sex": 1,
            "logo": null,
            "token": "c9xpghlmgxn58kdq",
            "group_id": 1
        }]
    }
}

name 用户名
sex 性别,1男 0女
logo 用户头像,null或许头像url
token
认证令牌,在无法保险session的情景下,在央求别的接口中应该将token参数带入
group_id 用户所属的用户组

打响获得登陆后的页面

图片 4

 

2.1.询问分类

{
    "code": 0,
    "data": {
        "count": 2,
        "items": [
            {
                "id": 1,
                "name": "公共栏目",
                "comment": "",
                "upper_catalog_id": 0
            },
            {
                "id": 2,
                "name": "私有栏目",
                "comment": "",
                "upper_catalog_id": 0
            }
        ]
    }
}

id 编号
name 名称
comment 备注
“upper_catalog_id 上级分类编号, 0 表示近来分类是拔尖分类。

前段时间喜欢用python去抓一些页面玩,但都大致都以用get请求一些页面,再通过正则去过滤。

图片 5

插一段代码,我把mui的ajax又做了越来越的包装,对逾期实行了自动重试,而对invalid_token等景观也做相应处理:

5.1.断定是或不是必须登录

请求

{
    "code": 0,
    "err_desc": "no"
}

err_desc 属性描述了对登录的渴求。no 代表不强制供给, yes
表示必须供给登录。

上面部分为请求头,上面部分为呼吁是传的参数。由图片能够见见,页面通过表单提交了八个参数。分别为_csrf,usermane,password。

图片 6

var onSuccess = function(data){
    UserInfo.username(username);
    UserInfo.password(pwd_hash);
    UserInfo.token(data.token); //把获取到的token保存到storage中
    var wc = plus.webview.currentWebview();
    wc.hide(‘slide-out-bottom’);   
//此处如若是隐藏登录页回到从前的页面,实际你也能够干点儿其余
}

5.登录验证

网站分析

image

UserInfo.password = function(){
    if(arguments.length == 0){
        return plus.storage.getItem(‘password’);
    }
    if(arguments[0] === ”){
        plus.storage.removeItem(‘password’);
        return;
    }
    plus.storage.setItem(‘password’, arguments[0]);
};

4.询问播放地址

其次份代码

image

UserInfo.username = function(){
    if(arguments.length == 0){
        return plus.storage.getItem(‘username’);
    }
    if(arguments[0] === ”){
        plus.storage.removeItem(‘username’);
        return;
    }
    plus.storage.setItem(‘username’, arguments[0]);
};

1.4.赶回新闻结构

归来的json新闻数据结构具有从严的一致性,客户端能够行使相同的接收和剖析方法处理回来音信。
不难新闻
简易的回到音讯蕴涵对请求的处理结果,结构如下:

{
    "code":0,
    "err_desc":""
}

其中:
code 为0意味处理成功,其余值表示处理退步。
err_desc是对错误的叙述,在code为0时err_desc会被概括。
独特景况,在用户认证的login1和login2接口中,err_desc具有非同小可用途用法,具体参见接口描述。除那三个接口之外,err_desc都代表错误描述。
带业务数据的音信
局部重临消息除了饱含处理结果消息,还蕴藏业务数据记录集,结构如下:

 {
        "code":0,
        "data":{
            "count":1,
            "items":[...]
        }
    }

其中:
data 业务数据的根节点:
count 业务数据的条数,恐怕的值为0 ~ n
items
业务数据,是三个数组,数据条数由count属性定义。当count为0时,items属性恐怕为null可能不设有。
本文书档案后续章节中,在描述items成分的质量时,会简单一些品质的描述,即事实上调用接口重返的性质在本文书档案中恐怕会并未描述,那种情状下请直接忽略被忽视描述的属性值。本文书档案中描述的属性是事实上再次来到内容的多个子集,没有描述到的始末对集花费系统没有影响。
带分页数据的新闻
如若回去数据较多,服务器会对回到的数额开始展览分页,客户端能够依据页码请求钦定范围的多少。带分页音信的回到数据结构如下:

    {
    "code":0,
    "data":{
        "page":1,
        "page_size":"20",
        "pages":"1",
        "total":"2",
        "count":2,
        "items":[...]
                }
}

分页数据新闻在data成分下,意义如下:
page 当前页码
page_size 每页数据记录条数
pages 总共的页数
total 总数据条数
count 当前赶回页的数码条数
只要回去的多少带有分页消息,则足以在调用接口时选取page参数来呼吁内定页码的数量。

因此,大家的代码逻辑就有了。首先请求2遍登录页面。然后分析页面,获得csrf字符串。最后把这几个字符串和账号密码一起传给服务器用来报到。

image

那是相比较安全的艺术,用户在报到时,APP调用获取token的接口(比如),用post将用户名和密码的摘要传递给服务器,然后服务器比对数据库中的用户音讯,匹配则赶回绑定该用户的token(这貌似翻译为令牌,很直观的名字,一看就精晓是有了那玩意儿,就会对你放行),而数据库中,在用户的token表中也还要插入了那一个token相关的数码:这么些token属于何人?那些token的有效期是多长时间?那么些token当前登录的ip地址是?这一个token对应的deviceid是?……
那样固然token被精心截获,也不会造成太大的平安风险。因为从没用户名和密码,然后假如黑客通过那几个token伪造用户请求,我们在劳动器端接口被调用时就能够对发起呼吁的ip地址、user-agent之类的音信作比对,防止止伪造。再然后,若是token的有效期设得小,过会儿它就超时了,除非黑客能够穿梭截获你的token,不然她只好干瞪眼。(插一句题外话:看到此间,是否知情为什么不推荐在外边随便接入来历不明的wifi热点了?)
tips:token如何变迁?
能够依据用户的新闻及一些专擅消息(比如时间戳)再通过hash编码(比如md五 、sha1等)生成唯一的编码。
tips:token的安全级别,取决于你的实在须要,所以如若不是关系财产安全的圈子,并不提出太严厉(比如用户走着走着,3G换了个基站,闪断了刹那间IP地址变了,尼玛token过期了,那就属于为了不须求的安全丢了用户体验,当然若是变换的IP地址跨省的话照旧应当辨证一下的,想想QQ有时候会让填验证码就知晓了)。
tips:接口在回去消息时,能够分包这次请求的意况,比如成功调用,那么result[‘status’]可能便是’success’,而反之则是’error’,而只借使’error’,则result[‘errcode’]中就能够涵盖错误的来头,比如errcode中是’invalid_token’就足以告诉APP那个token过期或无效,那时APP应弹出登录框或然用地方存款和储蓄的用户名或密码再度恳请token(用户选拔“记住密码”,就活该在本土保存用户名和密码的摘要,方法见plus.storage的文书档案)。

5.2.login1

{
    "code": 0,
    "data": {
        "count": 1,
        "items": [
            {
                "id": 37,
                "chcode": "9luqgrnj5vvszmjw"
            }
        ]
    }
}

id session识别号,用于login2接口,原样传递给login2即可。
chcode
挑衅字符串,客户端按约定规则使用该字符串生成贰个hash值,然后调用login2接口。

你只怕感兴趣的文章:

image

刚才的章程,机智一点儿的读者大约会心存疑虑:那获取token时不依旧得精晓传输一回密码吗?
没错,你能够将以此拿到token的地点,用SSL来爱慕(比如),那样黑客便是截了包,最近半会儿也解不出什么新闻。
SSL证书的获得渠道很多,作者深信你总有点子查到,所以不赘述了。可是话说namecheap上的SSL证书比godaddy的要便于得多……(那是吐槽)
tips:前段时间OpenSSL漏洞让广大服务器遭殃,所以借使协调搭服务器,一定记得装补丁。
tips:能够把装有接口都弄成SSL的吧?能够。但会拖慢服务器,如若是安排并不自信的VPS,建议不折腾。

3.查询媒体财富

今日试了须臾间,模拟登八人网站。发现也相比简单。读懂本文要求对http协议和http会话有自然的知道。

ip地址被界定,必要拭目以俟1分钟的提醒:

调用后端接口

1.5.参考

[1] RFC 2616, Hypertext Transfer Protocol — HTTP/1.1[S].
[2] RFC 3986, Uniform Resource Identifier (URI): Generic
Syntax[S].
[3] Introducing JSON

经过登陆抓取,看到如此3个呼吁。

image

//那里固然你曾经经过DOM操作获取到了用户名和密码,分别保存在username和password变量中。
var username = xxx;
var password = xxx;
var pwd_hash = get_pwd_hash(password);

3.1.询问媒体财富

{
    "code": 0,
    "data": {
        "page": 1,
        "page_size": "20",
        "pages": 9,
        "total": "18",
        "count": 2,
        "items": [
            {
                "id": 79,
                "catalog_id": 2,
                "title": "vod - 8898",
                "sub_title": "G3视频",
                "abstract": null,
                "text": null,
                "resource_type": "vod",
                "cover": "/mserver/cms/covers/res_cover_79.jpg?1515729601",
                "duration": 98,
                "add_time": "2018-01-08 19:19:26",
                "view_times": 0,
                "open_status": 0
            },
            ...
        ]
    }
}

再次回到0个或八个能源音讯。
id 能源编号
catalog_id 所属分类编号
title 标题
sub_title 小标题
abstract 摘要描述
text 描述
resource_type vod或live
cover 封面地址
duration 播放时间长度
add_time 添加时刻
view_times 观察次数
open_status 开放情状

由代码能够清楚,requests.Session()运维会话对象后,第③回呼吁会活动把上2回的sessionID一起传过去。

图片 7

报到时呼吁一遍token,之后用token调用接口

概述

图片 8

image

if(UserInfo.has_login()){
    //打开必要体现给用户的页面,只怕是调用远端接口
}
else{
    wv_login.show(‘slide-in-up’);   //从底层向上海滑稽剧团出登录页面
}
在登录页面中,用户输入了用户名和密码后,并点击了”登录“按钮,大家下一步做怎么着?再插段代码(注意:此处使用的是自家刚刚代码中扩充的web_query函数,你也足以直接选取mui的ajax):

1.1.用途

向集成客户端提供查询数据和登录服务。
倘使财富须求授权才能查看和利用,请首先阅读“5.登录验证”小节。

http协议是二个种无状态的商议。为了使那种无状态变得有状态,因而引进了对话。简单的说,通过session去记录这几个情状。当3个用户率先次呼吁web服务的时候,服务器会变卦一个session,用于保存那一个用户的音讯。同时,在回到给用户端时,把那些sessionID保存在cookies里。当用户再2遍呼吁的时候,浏览器会把那些cookies带上。因而在劳动器端就能领悟很多次请求是还是不是为同一个用户。

image

报到和注册要丰富容易
那是十分的小手提式有线电话机端,用再好的输入法,打字也是不便利的,所以别把登录页设计得须求填很多事物。假如有可能的话,只填手提式有线话机号,让用户接受短信验证码就做到注册是极端可是的了。想博得愈来愈多新闻?想想大商行的APP是如何是好的,他们会告知用户,未来的个人资料完善程度是十分三,如果想取得更多积分,你须要填完。
tips:假使你想昭示在Appstore并且同时涵盖注册效能,那么注册页面必须做1个用户许可协议的链接,不然有大概通不过审核。

1.2.通讯商议

客户端和服务器通过HTTP协议通讯,客户端采纳HTTP
Get向服务器发送请求,服务器再次来到json格式的事务数据或操作结果给客户端。

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import requests
import re

# 头部信息
headers = {
 'Host':"localhost",
 'Accept-Language':"zh-CN,zh;q=0.8",
 'Accept-Encoding':"gzip, deflate",
 'Content-Type':"application/x-www-form-urlencoded",
 'Connection':"keep-alive",
 'Referer':"http://localhost/login",
 'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"
}

# 登陆方法
def login(url,csrf,r_session):
 data = {
 "_csrf" : csrf,
 "username": "xiedj",
 "password": "***"
 }

 response = r_session.post(url, data=data, headers=headers)
 return response.content


# 第一次访问获取csrf值
def get_login_web(url):
 r_session = requests.Session()
 page = r_session.get('http://localhost/login')
 reg = r'<meta name="csrf-token" content="(.+)">'
 csrf = re.findall(reg,page.content)[0]


 login_page = login(url,csrf,r_session)
 print login_page


if __name__ == "__main__":
 url = "http://localhost/login/checklogin"
 get_login_web(url)

image

再插点代码,基于plus.storage的用户消息类,注意:须求在plusReady之后再采纳。

1.3.接口请求

接口地址是叁个HTTP协议的url地址,具体格式是:

ip替换到实际服务器的ip或域名,假使端口不是默许端口,要求把端口加上。
token是表达字符串,在签到接口中获取,假诺没有登录则省略。
别的内容参见接口的概念。
当U大切诺基L请求参数值中隐含U奥迪Q7L地址保留字符时,应对参数值举办U帕杰罗L编码。
切实参见“CRUISERFC2396: Uniform Resource Identifiers (U奔驰G级I): Generic
Syntax”。
当呼吁参数包罗汉语字符时,应对粤语字符选取UTF-8编码。

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import requests
import re

# 头部信息
headers = {
 'Host':"localhost",
 'Accept-Language':"zh-CN,zh;q=0.8",
 'Accept-Encoding':"gzip, deflate",
 'Content-Type':"application/x-www-form-urlencoded",
 'Connection':"keep-alive",
 'Referer':"http://localhost/login",
 'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"
}

# 登陆方法
def login(url,csrf):
 data = {
 "_csrf" : csrf,
 "username": "xiedj",
 "password": "***"
 }

 response = requests.post(url, data=data, headers=headers)
 return response.content


# 第一次访问获取csrf值
def get_login_web(url):
 page = requests.get('http://localhost/login')
 reg = r'<meta name="csrf-token" content="(.+)">'
 csrf = re.findall(reg,page.content)[0]
 login_page = login(url,csrf)
 print login_page


if __name__ == "__main__":
 url = "http://localhost/login/checklogin"
 get_login_web(url)

图片 9

UserInfo.token = function(){
    if(arguments.length == 0){
        return plus.storage.getItem(‘token’);
    }
    if(arguments[0] === ”){
        plus.storage.removeItem(‘token’);
        return;
    }
    plus.storage.setItem(‘token’, arguments[0]);
};
这么当用户运转APP或应用了亟需报到才能使用的作用时,就足以应用UserInfo.has_login()来判断是还是不是已经报到,即使已登录,则动用UserInfo.token()来博取到token数据,作为参数调用远程的后端接口。

上述就是本文的全体内容,希望对我们的学习抱有帮助,也期待我们多多协理脚本之家。

image

//清除登录音讯
UserInfo.clear = function(){
    plus.storage.removeItem(‘username’);
    plus.storage.removeItem(‘password’);
    plus.storage.removeItem(‘token’);
}

到那,应该都知情了,如若要登录成功,须要化解什么让服务相信一回呼吁是同三个用户。那里必要动用http会话(不知底的能够活动百度,那里大致介绍)。

开拓web登录页面,查看源代码,找找算法

//检查是或不是带有自动登录的新闻
UserInfo.auto_login = function(){
    var username = UserInfo.username();
    var pwd = UserInfo.password();
    if(!username || !pwd){
        return false;
    }
    return true;
}

爬虫的必需第三步,分析目的网站。这里运用谷歌(谷歌)浏览器的开发者者工具分析。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图