一、Golang模拟用户登陆,突破教务系统

1.1 请求登陆页面

整个流程中的第一步是获取登陆页面,就像下图这样人为的通过浏览器访问服务端,服务端返回反馈返回登陆页面

访问登陆页面的目的上图中标注出来了,为了获取到Cookie,给真正发起登陆到请求方法使用。

下面的golang发送http到get请求,获取登陆页面的代码:

// 访问登陆也,获取cookie
func GetCookieFromLoginhtml(url string) (cookie string, e error) {
res, err := http.Get(url)
if err != nil {
e = err
}
// 获取cookie
cookie = res.Header.Get("Set-Cookie")
cookie = util.GetOneValueByPrefixAndSurfix("JSESSIONID=", "; Path=/", cookie)
res.Body.Close()
return
}

1.2 抓包分析登陆请求

输入账号账号密码后点击登陆,将向后端发送登陆请求,如下图:

分析向后端发送到登陆请求都携带了哪些请求参数,携带了哪些请求头信息,以及需要通过Content-Type判断,该如何处理form表单中的数据发送到后台。后台才能正常响应。

在浏览器的控制台中我们可以去看下登陆页面源码

登陆页面对应的js源码

1.3 golang使用js引擎合成salt

这一步也是必须的,所谓获取salt,其实就是通过golang使用js引擎执行encodeInp(xxx), 这样我们才能得到经过加密后的username和password,进一步获取到encoded

import (
"github.com/robertkrimen/otto"
"io/ioutil"
)
func EncodeInp(input string)(result string,e error) {
jsfile := "js/encodeUriJs.js"
bytes, err := ioutil.ReadFile(jsfile)
if err != nil {
e = err
}
vm := otto.New()
_, err = vm.Run(string(bytes))
if err != nil {
e = err
}
enc,err :=vm.Call("encodeInp",nil,input)
if err != nil {
e = err
}
result = enc.String()
return
}

js部分的代码就不往外贴了,可以去下面的github地址中获取

1.4 模拟表单提交,完成登陆

使用golang模拟登陆请求

// 模拟登陆
func login(salt, cookie string) (html string) { req, err := http.NewRequest("POST", LoginUrl, strings.NewReader("encoded="+salt)) // 添加请求头
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36")
req.Header.Add("Cookie", "JSESSIONID="+cookie)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9") //发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("无密版qlu教务系统登陆请求失败 : %v", err)
return
}
// todo 根据状态码判断下一步如何操作,如果状态码是302,表示操作成功
fmt.Println("resp.Status: ", resp.Status) b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("error : %v", err)
return
}
// 返回个人主页的html
html = string(b)
// 手动关闭
resp.Body.Close()
return
}

这一步中值得注意的地方:

第一:我们发送的请求的类型是POST请求

第二:我们应该如何处理form表单中的数据后,再发送给后端,后端才能正常处理呢?

具体处理成什么样,是需要根据请求头中的Content-Type决定的。

不知道大家知不知道常见的Content-Type的几种类型:在form 表单中有一个属性叫做 entype可以间接将数据处理成Content-Type指定数据格式, 比如我们可以像这样设置:

  • enctype = text/plain 那么form表单最终提交的格式就是: 用纯文本的形式发送。

  • enctype = application/x-www-form-urlencoded

    • 表单中的enctype值如果不设置,则默认是application/x-www-form-urlencoded,它会将表单中的数据变为键值对的形式。
    • 如果action为get,则将表单数据编码为(name1=value1&name2=value2…),然后把这个字符串加到url后面,中间用?分隔。
    • 如果action为post,浏览器把form数据封装到http body中,然后发送到服务器。
  • enctype = mutipart/form-data

    • 上传的是非文本内容,比如是个图片,文件,mp3。

根据这个知识点,结合我们当前的情况,method=post,Content-Type = application/x-www-form-urlencoded

所以,在选择golang的api时,我们选择下图这个api使用

1.5 进入成绩查询页,解析用户成绩

如果不出意外,经过上面的处理,我们已经完成登陆,并且获取到后台页面的html源码了。

再之后我们就直奔成绩查询模块,还是使用如何的分析思路

func getAllScore(stuIdentify, cookie string) ([]mtStruct.Score, error) {
// 发送查询成绩的请求
u := "http://jwxt.qlu.edu.cn/jsxsd/kscj/cjcx_list"
req, err := http.NewRequest("POST", u, strings.NewReader("kksj=&kcxz=&kcmc=&xsfs=all"))
if err != nil {
fmt.Printf("error : %v", err)
return nil, err
}
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36")
req.Header.Add("Cookie", "JSESSIONID="+cookie)
req.Header.Add("Referer", "http://jwxt.qlu.edu.cn/jsxsd/kscj/cjcx_query?Ves632DSdyV=NEW_XSD_XJCJ")
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*;q=0.8,application/signed-exchange;v=b3;q=0.9") client := &http.Client{}
resp, err := client.Do(req)
... }

代码详情可以去github上查看。

二、植入微信公共号后台

上面的功能实现后再结合Golang开发微信公众号就能实现一款好玩的应用。

让用户通过微信公共号平台和后端进行数据的交互,我们获取到用户的信息,拿着用户的信息帮用户监听教务系统的成绩单的状态。一旦有成绩第一时间推送给用户。

点击查查看公众号端设计思路


项目GitHub地址:https://github.com/zhuchangwu/golang-wechat-backend

Golang模拟用户登陆,突破教务系统的更多相关文章

  1. C#中模拟用户登陆SharePoint网站

    自动化测试一个SharePoint网站,首先要登陆,我们今天就模拟一下用户登陆SharePoint网站的过程,这一过程可以通过其他方式完成模拟,比如通过Coded UI Test录制脚本会更方便,但是 ...

  2. 《java入门第一季》模拟用户登陆注册案例集合版

    需求:校验用户名和密码,登陆成功后玩猜数字小游戏. 在这里先写集合版.后面还有IO版.数据库版. 一.猜数字小游戏类: 猜数字小游戏的代码见博客:http://blog.csdn.net/qq_320 ...

  3. 37.4 net--TcpDemo2模拟用户登陆

    package day35_net_网络编程.tcp传输.模拟用户登录; import java.io.*; import java.net.InetAddress; import java.net. ...

  4. jdbc连接模拟用户登陆密码判断

    package com.aaa.demo1; import com.aaa.utils.JdbcUtils; import java.sql.Connection; import java.sql.P ...

  5. Java模拟登录带验证码的教务系统(原理详解)

    一:原理 客户端访问服务器,服务器通过Session对象记录会话,服务器可以指定一个唯一的session ID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求. 我们通过Chrome浏 ...

  6. 使用php的curl爬去青果教务系统 课表(转)

    1. 分析 首先我们要了解 Http Cookie 的作用(可参考HTTP cookies 详解),简单来说就是维持一个会话,这样我们就能在登陆一个网页后,就能进入这个网页需要登陆的界面. 现在我们需 ...

  7. 模拟Post登陆带验证码的网站

    前言: 作者在一个项目需求 模拟用户登陆,获取该用户的订单记录. 该系统需要用户名,密码,验证码 (验证码为正楷的数字4位),于是参考网络一些文章,并进行了很多测试,总结步骤如下: 步骤1 : 通过h ...

  8. python爬虫学习(4) —— 手刃「URP教务系统」

    0. 本爬虫目标 模拟登陆URP教务系统 查询 本学期/历年 成绩 计算历年成绩的绩点 下面是一点废「私」话「货」: 一般情况,查询成绩大家会通过如下方式: 登陆信息门户 -> 转到教学空间 - ...

  9. 基于gin框架和jwt-go中间件实现小程序用户登陆和token验证

    本文核心内容是利用jwt-go中间件来开发golang webapi用户登陆模块的token下发和验证,小程序登陆功能只是一个切入点,这套逻辑同样适用于其他客户端的登陆处理. 小程序登陆逻辑 小程序的 ...

随机推荐

  1. maven基本配置

    1.maven 是一个项目构建工具,如果在公司做大的项目 ,需要把项目拆分成很多子项目,为了方便各子项目之间协同开发和调试,一般都会使用maven.使用maven和以前web项目最大的不同是jar包的 ...

  2. LeetCode--LinkedList--206. Reverse Linked List(Easy)

    206. Reverse Linked List(Easy) 题目地址https://leetcode.com/problems/reverse-linked-list/ Reverse a sing ...

  3. 【Spark】这一篇或许能让你大概了解如何通过JavaAPI实现DataFrame的相关操作

    文章目录 需求概述 步骤 一.创建Maven工程并导包 二.选用第一种方法:利用反射机制配合样例类构建DataFrame 开发代码 选用第二种方法:通过StrucType配合Row构建DataFram ...

  4. Owin Katana 的底层源码分析

    最近看了一下开源项目asp.net katana,感觉公开的接口非常的简洁优雅,channel 9 说是受到node.js的启发设计的,Katana是一个比较老的项目,现在已经整合到asp.net c ...

  5. [hdu4911]逆序对相关

    思路:由于只能交换相邻的数,所以每次最多减小1个逆序对(且如果存在逆序对那么肯定可以减小1个)!于是乎..就是统计逆序对的裸题了.树状数组或归并都行. #pragma comment(linker, ...

  6. Java多线程带返回值的Callable接口

    Java多线程带返回值的Callable接口 在面试的时候,有时候是不是会遇到面试会问你,Java中实现多线程的方式有几种?你知道吗?你知道Java中有可以返回值的线程吗?在具体的用法你知道吗?如果两 ...

  7. java经典问题 byte b=1、b=b+1、b+=1

    直接问题: 首先 byte的范围 [-128,127] byte 类型可以自动转为int类型 int类型不能自动转为byte类型. 超过byte的范围,就会变成int类型了 byte b=1:正确, ...

  8. 黑马程序员_毕向东_Java基础视频教程——switch语句练习(随笔)

    switch(练习) /* if和 switch 语句很像. 具体什么场景下使用什么语句呢? 如果判断的具体数值不多且符合byte.short.int.char.String类型,虽然两个语句都可以使 ...

  9. (Python基础教程之二十二)爬虫下载网页视频(video blob)

    Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...

  10. Shell脚本定时监控

    1.建立脚本文件 autostart.sh #!/bin/bashexport JAVA_HOME=/home/java/jdk1.8.0_191export JRE_HOME=$JAVA_HOME/ ...