基于python和cURL实现网络服务自动认证

基于python和cURL实现网络服务自动认证

bigben@seu.edu.cn 2016/4/15
Tags: Python, cURL, 网络接入


如今校园网上网一般都采用Web认证方式,即首先登陆网关页面,输入用户名和密码,认证成功后可以进行Internet接入,服务器端开始计费。例如移动的CMCC-EDU、联通的ChinaUnicom、电信的ChinaNet无线接入,都采用这种认证方式。此外东南大学校园网Internet接入也采用这种方式,当用户连接上seu-wlan后,客户端会自动获得一个IP地址,但是此时用户还不能访问外网。当用户在浏览器地址栏中输入www.baidu.com时,网页会自动重定向到w.seu.edu.cn。这就是东南大学上网认证的portal。

但是这样每次上网都需要启动浏览器,并输入用户名和密码,操作比较繁琐。此外,如果是通过ssh连接到远程主机,则用户只有一个虚拟终端,只能通过命令行进行操作,无法启动浏览器。此时如果用户需要连接外网怎么办?显然,如果这些认证工作能够绕开浏览器,直接在命令行下完成,那么所有问题都可以迎刃而解。这样只需在命令行下敲几行命令或者将相关操作写成脚本,下次直接运行这个脚本进行自动认证,无疑能极大提高效率。下面我们就对东南大学的网络认证portal做一下小小的hack来实现这一设想。

首先,我们获取w.seu.edu.cn的首页https://w.seu.edu.cn/portal/index.html源码,具体操作步骤为:
在浏览器中输入网址:https://w.seu.edu.cn/portal/index.html,右键点击查看源码即可。

如果用户安装了wget或者cURL, 也可以输入以下命令来获取首页:

wget https://w.seu.edu.cn/portal/index.html

OR

curl https://w.seu.edu.cn/portal/index.html

接下来我们分析一下首页的源码。搜索并定位到网页认证表单相关的代码,如下所示:

<form id="loginForm" name="loginForm" method="post" action="">

我们重点关注一下methodaction属性。由代码可知:系统采用POST方式上传数据,但是action属性为空(一般action属性都设置为某个网址,即将表单数据上传到那个网址进行处理。此处action为空是因为网页通过JavaScript脚本进行处理,与数据提交相关的代码在JavaScript脚本中)。
接着我们发现在网页头部加载了一个JavaScript脚本,如下所示:

<script type="text/javascript" src="js/portal.js"></script>

下载这个js文件,我们对其源码进行分析。

这份代码不是很长,经过分析我们可以找到下面两处代码,分别对应login和logout的处理(熟悉jQuery的童鞋应该能够看懂)。

Login:

login-form.png

Logout:

logout-form.png

注意图中红色框中的内容,从中可知login和logout时是利用ajax将表单中数据POST到远端地址,并且数据格式为json,编码方式为utf-8。login时,提交的URL为login.php,即https://w.seu.edu.cn/portal/login.php, 提交的数据包括两项:username和password。对相应地,logout时向https://w.seu.edu.cn/portal/logout.php提交数据即可,数据为空。

至此,我们已经弄清楚了Web认证的全部流程。下面就可以在命令行下模拟这一过程,从而实现命令行下的网络服务认证登录。

如果用户已经安装了cURL,直接输入下面的命令。

Login

curl -A 'Mozilla' -d "username=<username>&password=<password>" http://w.seu.edu.cn/portal/login.php

<username><password>换成你自己的用户名和密码即可。

Logout

curl -A 'Mozilla' -d "" http://w.seu.edu.cn/portal/logout.php

cURL -A选项用于设置User-Agent,可以省略不写。而cURL通过-d选项POST数据,正是本次hack的核心所在。

为了实现自动登录,只需要将上述命令保存为一个shell脚本,下次直接运行这个脚本即可。或者将该命令加入rc.local中。

#! /bin/bash

function do_login() {
    username=$1
    password=$2
    curl -d "username=${username}&password=${password}" http://w.seu.edu.cn/portal/login.php
}

function do_logout() {
    curl -d "" http://w.seu.edu.cn/portal/logout.php
}

case "$1" in
    login)
        shift
        echo "connecting server at w.seu.edu.cn/portal/login.php"
        do_login "$@"
        [ ! $? == 0 ] && echo "abc.sh login <username> <password>"
        echo -e "\n"
        ;;
    logout)
        echo "connecting server at w.seu.edu.cn/portal/logout.php"
        do_logout
    version)
        echo "version: 1.0.0"
        ;;
    help|*)
        echo "abc.sh login|logout|version|help"
        ;;
esac

我们也可以利用Python脚本来实现这些功能。对于这种简单的操作来说,使用Python似乎有点小题大做,但是利用Python可以实现更强大的功能,例如从命令行输入用户名和密码,以及对服务器返回状态的解析等等。以下是Python代码,供参考。

#! /usr/bin/python
import sys, getopt
import urllib, json

__author__ = "bigben@seu.edu.cn"
__version__ = "1.0.0"

# login
def login(params):
    response = _post_data("http://w.seu.edu.cn/portal/login.php", params)
    _dump_status(response)

# logout
def logout():
    response = _post_data("http://w.seu.edu.cn/portal/logout.php", '')
    _dump_status(response)

def _post_data(url, data):
    return urllib.urlopen(url, urllib.urlencode(data)).readlines()[1]

# dump_status (response is JSON-formatted string)
def _dump_status(response):
    status = json.loads(response)
    print("Status: ")
    for k in status:
        print("%-15s: %s" %(k, status[k]))

def usage():
    print("abc v 1.0.0\nby bigben@seu.edu.cn\nabc help|version|login|logout")

def do_login(args):
    try:
        opts, args = getopt.getopt(args, "u:p:", ["help", "version", "user=", "password="])
    except getopt.GetoptError as err:
        # print help information and exit:
        print str(err)
        usage()
        sys.exit(2)

    params = {'username' : "", 'password' : ""}
    for o, a in opts:
        if o == "-v":
            print("Version: %s", "1.0.0")
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-u", "--user"):
            params['username'] = a
        elif o in ("-p", "--password"):
            params['password'] = a
        else:
            assert False, "unhandled option"
    login(params)

def do_logout():
    logout()

if __name__ == '__main__':
    if (len(sys.argv) < 2):
        print("operation must be specified, valid operation(s) are help|version|logint|logout")
        usage()
        sys.exit(-1)

    cmd = sys.argv[1]
    if cmd == "help":
        usage()
        sys.exit()
    elif cmd == "version":
        print("Version: %s" %"1.0.0")
        sys.exit()
    elif cmd == "login":
        do_login(sys.argv[2:])
    elif cmd == "logout":
        do_logout()
    else:
        print('Invalid command: %s' %(cmd))

运行结果如下:

Login

login-with-python

此时如果刷新http://w.seu.edu.cn/portal/页面就会看到此时已经登录成功。

Logout

logout-with-python

最后,再补充点题外话,在Windows系统下,拨号连接也可以通过命令行来完成。
例如,橘园宿舍网口可以访问IPV6教育网资源,账号为test@seujs,密码为1234,接入后可以访问教育网内部资源。

用户需要首先新建一个拨号连接,将其命名为“Bras Seu”(名字可以随便起)。然后插入网线,在命令行输入以下命令进行即可连接:

rasdial "Bras Seu" test@seujs 1234

连接成功后在浏览器地址栏中输入"www.6rank.edu.cn"进行测试,若能正常访问,代表成功接入教育网。

在命令行下输入”rasdial /?”可以查看rasdial命令的帮助。
有兴趣的同学可以试试。


后记:这是半年前写的一篇技术博客,今天偶然翻出来了。最近校园网认证系统正在进行升级,不知道上面的脚本是否还能生效,等改天有时间再好好研究一下。

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用中提到,网络爬虫是一种用于获取网页信息的程序,它可以模拟人类在浏览器中访问网页的行为,并将获取到的数据进行处理和存储。在使用Python进行网络爬虫时,首先需要掌握Python基础知识,比如使用urllib库进行网络请求,使用字符串操作进行数据处理,以及掌握基本的程序逻辑。其中,正则表达式也是常用的数据提取工具。当你具备了这些知识和技能,你就可以开始编写Python爬虫程序来获取小说网站上的内容了。 引用中提到,curl是一个用于发送HTTP请求的命令行工具,也可以通过Python的subprocess库来调用curl命令。在使用curl进行HTTP请求时,可以通过设置headers中的参数来指定不同的接受数据类型,并将获取到的文件保存到本地。举个例子,通过设置accept参数为image/png,可以获取到PNG格式的图片文件;通过设置accept参数为image/webp,可以获取到WebP格式的图片文件;通过设置accept参数为image/jpeg,可以获取到JPEG格式的图片文件。 引用中介绍了一些常用的curl命令参数及其用法。比如,-A参数用于设置user-agent,可以模拟不同浏览器的访问;-X参数用于指定请求的方法,如GET、POST等;-I参数只返回请求的头信息,不包含响应体;-d参数用于发送POST请求的参数;-O参数用于下载文件并以远程的文件名保存;-o参数用于下载文件并以指定的文件名保存;-L参数用于跟随重定向请求;-H参数用于设置请求的头信息;-k参数用于允许发起不安全的SSL请求;-b参数用于设置cookies。 接下来是你的问题回答: Pythoncurl是一个基于libcurl库的Python模块,它提供了一个简单而强大的接口,用于发送HTTP请求,并获取响应数据。通过Pythoncurl模块,你可以方便地进行网页抓取、API访问等操作。使用curl模块,你可以设置请求的headers、cookies,发送GET、POST等各种类型的请求,并对响应数据进行处理和解析。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值