第五课 Flask数据传输加密

Flask 第五课数据传输加密

tags:

  • Flask
  • 2019千锋教育

categories:

  • flask
  • 数据加密
  • 反爬虫技术

第一节 数据准备

  1. 数据加密前视图函数views.py和news_list.html如下。
@blue.route('/addnews/')
def add_news():
    news = News()
    news.n_title = "小搞怪 %d" % random.randrange(1000)
    news.n_content = "社会福利 %d" % random.randrange(100)
    db.session.add(news)
    db.session.commit()
    return '添加新闻列表成功'


@blue.route('/getnews/')
def get_news():
    news_list = News.query.all()
    return  render_template('news_list.html', news_list=news_list)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>News list</title>
</head>
<body>
<h2>今日新闻</h2>
<ul>
    {% for news in news_list %}
        <li>{{ news.n_content }}</li>
    {% endfor %}
</ul>
</body>
</html>
  1. 爬虫脚本
import requests

def get_data():
    response = requests.get("http://127.0.0.1:5000/getnews/")
    print(response.content.decode("utf-8"))

if __name__=="__main__":
    get_data()

第二节 JS加载和数据加密

2.1 通过js加载出数据

  1. 创建数据html, news_content.html页面。
  2. {{ news_content|safe }} 当成html格式输出。
<!--news_list.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>News list</title>
</head>
<body>
<h2>今日新闻</h2>
<script type="text/javascript">
    document.write("{{ news_content|safe }}")
</script>
<!--{ news_content|safe }}-->
</body>
</html>
<!--news_content.html, 写成一行的格式(否则加载到news_list会报错)-->
<ul>{% for news in news_list %}<li>{{ news.n_content }}</li>{% endfor %}</ul>
# views.py
@blue.route('/getnews/')
def get_news():
    news_list = News.query.all()
    news_content = render_template("news_content.html", news_list=news_list)
    return  render_template('news_list.html', news_content=news_content)

2.2 对数据进行加密

  1. 我们使用的解密js函数如下。show.js
  2. 它先对整体字符串解密,去掉前后约定字符串后,再次解密
function base64Decode(input) {
    _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    while (i < input.length) {
        enc1 = _keyStr.indexOf(input.charAt(i++));
        enc2 = _keyStr.indexOf(input.charAt(i++));
        enc3 = _keyStr.indexOf(input.charAt(i++));
        enc4 = _keyStr.indexOf(input.charAt(i++));
        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;
        output = output + String.fromCharCode(chr1);
        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }
    }
    _utf8_decode = function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
        while (i < utftext.length) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if ((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = utftext.charCodeAt(i + 1);
                c3 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    };
    output = _utf8_decode(output);
    return output;
}

function showDeHtml(J1) {
    return base64Decode(
        (base64Decode(J1)["\x72\x65\x70\x6c\x61\x63\x65"]('\x43\x48\x4b\x61\x32\x47\x46\x4c\x31\x74\x77\x68\x4d\x44\x68\x45\x5a\x56\x66\x44\x66\x55\x32\x44\x6f\x5a\x48\x43\x4c\x5a\x6b', ''))
            ["\x72\x65\x70\x6c\x61\x63\x65"]('\x70\x4f\x71\x33\x6b\x52\x49\x78\x73\x32\x36\x72\x6d\x52\x74\x73\x55\x54\x4a\x76\x42\x6e\x39\x5a', '')
    )
}

/**
 *
 *          base64Decode(
 *              base64Decode(content)['replace']('CHKa2GFL1twhMDhEZVfDfU2DoZHCLZk',''))
 *                    ['replace']('pOq3kRIxs26rmRtsUTJvBn9Z','')
 *
 *         base64Decode( base64Decode(content).replace('CHKa2GFL1twhMDhEZVfDfU2DoZHCLZk', '').replace('pOq3kRIxs26rmRtsUTJvBn9Z', '') )
 *
 */
  1. 后端对返回数据进行加密
import base64
@blue.route('/getnews/')
def get_news():
    news_list = News.query.all()
    news_content = render_template("news_content.html", news_list=news_list)
    # 字符串转二进制 加密后成二进制在转成字符串
    encode_content = base64.standard_b64encode(news_content.encode("utf-8")).decode("utf-8")
    print(encode_content)
    # 拼串 加入和前端约定好的前后字符串
    add_content_encode_content = "CHKa2GFL1twhMDhEZVfDfU2DoZHCLZk" + encode_content + "pOq3kRIxs26rmRtsUTJvBn9Z"
    print(add_content_encode_content)
    encode_content_twice = base64.standard_b64encode(add_content_encode_content.encode("utf-8")).decode("utf-8")
    print(encode_content_twice)
    return render_template('news_list.html', news_content=news_content, encode_content_twice=encode_content_twice)
  1. 前端对返回数据进行解析。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>News list</title>
    <script type="text/javascript" src="{{ url_for('static', filename='js/show.js') }}"></script>
</head>
<body>
<h2>今日新闻</h2>
<script type="text/javascript">
    /*document.write("{{ news_content|safe }}");*/
    document.write(showDeHtml("{{ encode_content_twice|safe }}"));
</script>
<!--{ news_content|safe }}-->
</body>
</html>
  1. 如果在直接爬取网页信息,就只能看到一堆加密的字符串。但是我们可以看到有一个自己的show.js资源。
    • 如果我们把它下载下来,对加密算法进行分析解密。还是可以获取到我们的数据。下面我们尝试吧show.js给隐藏掉。
    • 也可以使用浏览器的JS容器加载,由python文件调用。

第三节 隐藏加密js文件

  1. 写一个接口由接口返回我们的js文件。
  2. 接口具有时效性,超过1秒自动时效
@blue.route('/getshow/')
def get_show():
    import os, time
    from flask import request
    from App.settings import BASE_DIR
    # 接收前端的时间参数
    t = request.args.get("t")
    print(t)
    # python中以秒为计数单位,其他语言以毫秒计数单位
    c = time.time() * 1000
    # 捕获异常(防止手动乱输入)
    try:
        t = int(t)
    except:
        return "2"
    # 1秒之内请求可以正常返回js
    if c > t and c - t < 1000:
        with open(os.path.join(BASE_DIR, "static\js\show.js"), 'r') as file:
            js_content = file.read()
            print(js_content)
        return js_content
    else:
        return "1"
  1. 动态访问接口获取js文件。并传入时间参数。
  2. 这种方法有效避免直接通过页面获取js文件。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>News list</title>
    <!-- 传入时间下面方法不适用因为用不了JS的时间函数,使用动态加载 -->
    <!--<script type="text/javascript" src="{{ url_for('blue.get_show') }}"></script>-->
    <script type="text/javascript">
        // 这个在前台控制台Elements中才能看见 source中看不到
        document.write('<script type="text/javascript" src="/getshow/?t='+Date.parse(new Date())+'"><\/script>');
    </script>
</head>
<body>
<h2>今日新闻</h2>
<script type="text/javascript">
    /*document.write("{{ news_content|safe }}");*/
    document.write(showDeHtml("{{ encode_content_twice|safe }}"));
</script>
<!--{ news_content|safe }}-->
</body>
</html>

第四节 总结

  1. 如果通过爬虫文件,直接爬取。会返回一堆js代码。

  2. 爬虫获取的是前端控制台Source的内容,而不是Element的内容。

  3. 当然这种反爬虫也不是最强大的,我们可以通过**浏览器的console输出加密函数*
    在这里插入图片描述

  4. 爬虫基本步奏

    • 数据获取
      • 麻烦
    • 数据提取
    • 数据存储
      • 数据清洗
  5. 反爬

    • 数据加密反爬
    • 在服务端对数据进行特定算法的加密
    • 在客户端进行数据的解密
      • 浏览器还是可破解的
      • Android或IOS移动端,破解率基本为零
发布了61 篇原创文章 · 获赞 8 · 访问量 2804

猜你喜欢

转载自blog.csdn.net/aa18855953229/article/details/104881130