zoukankan      html  css  js  c++  java
  • 【Java】模拟登录教务网并获取数据

    本文章仅做技术交流演示学习,请勿用于违法操作!

    前期准备

    首先我们需要到要模拟登录的网页,进行抓包操作。

    使用Chrome浏览器打开系统的登录页面,按F12打开开发者工具

    切换到Network选项卡

    然后正常进行登录操作。

    登录成功后,可以在右面看到加载出很多的数据,我们需要逐一查看Headers找到对应的登录接口

    如图所示,大部分都是login相关的页面名称。

    很显然,这个接口URL即我们想要的请求登录接口。

    RequestURL:http://打码/jsxsd/xk/LoginToXk

    根据登录界面和FormData 我们知道,登录提供的是账户和密码,但是浏览器在请求的时候是三个参数,分别为:userAccount,userPassword,encoded

    显然userAccount即我们提供的账号,userPassword是密码但为空,encoded是一堆看不懂的密文

    初步推测是encoded应该是加密过后的密码

    那么加密过程一定是在前端完成的,我们根据经验加密函数应该也是使用js写的。

    回到登录界面,开启开发者模式,刷新一下,果然在列表中有一个名为conwork.js的文件

    该文件就是用来对密码进行加密的文件,我们将其保存下来。

    eval(function(p, a, c, k, e, d) {
        e = function(c) {
            return (c < a ? "" : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
        }
        ;
        if (!''.replace(/^/, String)) {
            while (c--)
                d[e(c)] = k[c] || e(c);
            k = [function(e) {
                return d[e]
            }
            ];
            e = function() {
                return '\w+'
            }
            ;
            c = 1;
        }
        ;while (c--)
            if (k[c])
                p = p.replace(new RegExp('\b' + e(c) + '\b','g'), k[c]);
        return p;
    }('b 9="o+/=";p q(a){b e="";b 8,5,7="";b f,g,c,1="";b i=0;m{8=a.h(i++);5=a.h(i++);7=a.h(i++);f=8>>2;g=((8&3)<<4)|(5>>4);c=((5&s)<<2)|(7>>6);1=7&t;k(j(5)){c=1=l}v k(j(7)){1=l}e=e+9.d(f)+9.d(g)+9.d(c)+9.d(1);8=5=7="";f=g=c=1=""}u(i<a.n);r e}', 32, 32, '|enc4||||chr2||chr3|chr1|keyStr|input|var|enc3|charAt|output|enc1|enc2|charCodeAt||isNaN|if|64|do|length|ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789|function|encodeInp|return|15|63|while|else'.split('|'), 0, {}))

    到此,前期准备就完成了。

    模拟登录

    本文使用Java来进行编写,其他语言原理类似。

    Java运行JS代码

    首先要解决的就是,如何能在java代码中运行这个使用js编写的加密函数。

    当然,如果有能力看懂的话,你也可以重写一遍这个方法,可以跳过本段内容。

    我们使用的是Java自带的解决方案:ScriptEngineManager

    首先编写一个通用方法:

      /**
         * 从给定的js文件中获取指定接口中的方法的实例
         * @param js js字符串
         * @param clazz 接口的class
         * @return 返回一个指定接口方法的实例
         */
        public <T> T getMethod (Class<T> clazz,String js) {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("js");
            try {
                //1.可以直接读取指定目录下的文件
                //String path = ExecuteScript.class.getResource("").getPath();
                //System.out.println(path);
                // FileReader的参数为所要执行的js文件的路径
                //engine.eval(new FileReader(fileLoacation));
                //2.直接加载字符串
                engine.eval(js);
                if (engine instanceof Invocable) {
                    Invocable invocable = (Invocable) engine;
                    T executeMethod = invocable.getInterface(clazz);
                    return executeMethod;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

    然后根据Js的方法创建一个接口,接口中的方法名称要和js中的方法名称对应。

    public interface JSMethods {
        public String encodeInp(String input);
    }

    使用方法:

    /**
         * 加密
         * @param onecard 学号
         * @param password 密码
         * @return 加密的学号+%%%+加密的密码
         * */
        private   String getEncodeString(String onecard,String password){
            ExecuteScript executeScript = new ExecuteScript();
            //String fileLocation="src/main/resources/templates/conwork.js";
            //通过下面一行代码就可以获取指定接口中方法的实例
            JSMethods method = executeScript.getMethod(JSMethods.class,JscriptMethod.data);
            String result=method.encodeInp(onecard);
            String pass=method.encodeInp(password);
            return result+"%%%"+pass;
        }

    这里的result是根据实际encoded结果分析出来的。

    使用Okhttp进行模拟Post请求

    首先创建请求体:requestbody

     RequestBody requestBody=new FormBody.Builder()
                    .add("userAccount",account)
                    .add("userPassword","")
                    .add("encoded",getEncodeString(account,password))
                    .build();

    必须与我们前面分析出来的请求参数一一对应。

    接着我们创建一个request请求:

    Request request=new Request.Builder()
                    .url(REQUEST_JW_URL)
                    .header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
                    .header("User-Agent","Mozilla")
                    .post(requestBody)
                    .build();

    这里的请求头,可以参考浏览器获取的结果

    然后使用okhttpclient发起post请求即可,根据response判断是否登录成功

    /**
         * 模拟登陆
         * @param account 学号
         * @param password 密码
         * */
        private String login(String account,String password){
            String result="";
            RequestBody requestBody=new FormBody.Builder()
                    .add("userAccount",account)
                    .add("userPassword","")
                    .add("encoded",getEncodeString(account,password))
                    .build();
            Request request=new Request.Builder()
                    .url(REQUEST_JW_URL)
                    .header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
                    .header("User-Agent","Mozilla")
                    .post(requestBody)
                    .build();
            try {
                Response response=client.newCall(request).execute();
                result=response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }

    如果需要登录后进行访问其他页面获取数据,这里只需要配置一下okhttp的cookies管理工具:

     public OkHttpClient client = new OkHttpClient.Builder()//这个cookies就不存在本地了,因为不需要验证码直接登录,每次刷新就好
                .cookieJar(new CookieJar() {
                    @Override
                    public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
                        cookieStore.put(httpUrl.host(), list);
                    }
    
                    @Override
                    public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                        List<Cookie> cookies = cookieStore.get(httpUrl.host());
                        return cookies != null ? cookies : new ArrayList<Cookie>();
                    }
                })
                .build();

    全局都使用该client进行请求即可,注意无论是同步还是异步操作都要保证login成功

  • 相关阅读:
    安全工具
    WebRTC媒体协商及实践
    流媒体协议介绍(rtp/rtcp/rtsp/rtmp/mms/hls)
    基于 WebRTC 技术的实时通信服务开发实践
    实时音视频互动系列(下):基于 WebRTC 技术的实战解析
    WebRTC基于浏览器的开发
    webRtc+websocket多人视频通话
    Android IOS WebRTC 音视频开发总结(四九) ffmpeg介绍
    Android IOS WebRTC 音视频开发总结(二五) webrtc优秀资源汇总
    The 3n + 1 problem UVA 100
  • 原文地址:https://www.cnblogs.com/robotpaul/p/12378283.html
Copyright © 2011-2022 走看看