day24-XSS过滤及单实例

一、前言

  我们在提交文本到后台的时候,比如我们在写博客的过程中,如果有人在博客中写入 <script>alert(123)</script>  等,如果你在后台不把它过滤掉,那就会受到攻击,你的网站压根就没有办法用,那有什么办法过滤呐,今天我们就用一个 BeautifulSoup 这个模块来过滤一些,那如果使用这个模块呐,在使用之前必须安装这个模块:

pip install beautifulsoup4

ok,我们下面就来看看,如果使用这个模块,来过滤 XSS。

二、XSS过滤

2.1、操作的html

说明:以下的代码,都是针对我们所操作的html

content = '''
    <p>
        dwqdq<span style="font-family:NSimSun">sqsqsqsq</span>
    </p>
    <p>
        <strong id='d10'>dwqdqw</strong>
        <script>alert(123)</script>
    </p>
    <h2>qwdqwd</h2>
'''

2.2、知识点

说明:在过滤之前,我们要掌握一些知识点

from bs4 import BeautifulSoup
#清空某个标签,比如攻击的script标签
soup = BeautifulSoup(content,'html.parser')
tag = soup.find('script')  #找到script 标签
tag.hidden = True  #表示让script这个标签隐藏
tag.clear() #把找到那个标签清空
print(tag)

#删除某个标签的属性
span = soup.find('span')
print(span.attrs)
del span.attrs['style']  #删除span标签style属性
print(span)

#把对象转换成字符串的形式
content = soup.decode()  
print(content)

2.2、只过滤标签

说明:如果我只过滤掉标签的话,不过滤标签属性

from bs4 import BeautifulSoup
#添加过了白名单
tags = ['p','strong']  #只允许添加p标签和strong标签
soup = BeautifulSoup(content,'html.parser')

for tag in soup.find_all(): #find_all()找到所有标签
    if tag.name in tags:
        pass
    else:
        tag.hidden = True
        tag.clear()

content = soup.decode()
print(content)

2.3、过滤标签和标签属性

说明:我不仅要过滤标签,还要过滤掉标签属性

from bs4 import BeautifulSoup
#白名单
tags = {
    'p':['class'],
    'strong':['id'],
}
soup = BeautifulSoup(content,'html.parser')
for tag in soup.find_all():
    if tag.name in tags:
        pass
    else:
        tag.hidden = True
        tag.clear()
        continue  #如果不在白名单,直接跳过
    # 用户提交标签的所有属性
    input_attrs = tag.attrs  # ['class':'c1','id':'i']
    valid_attrs = tags[tag.name]  #['class']

    for k,v in list(input_attrs.items()):  #input_attrs.items()会自动生成一个迭代器,del tag.attrs[k]是无法删除的
        if k in valid_attrs:
            pass
        else:
            del tag.attrs[k]

注意了:一般我们需要对后台提交过来的数据是要过滤的,特别是 kindEditor编辑器

三、单实例

  我们都知道,我们在创建对象的时候,创建多个对象占的内存资源一定比创建一个对象占的资源多很多,所以我们,应该采用单实例模式,就是永远用一个对象示例

 3.1、定义静态方法方式实现

说明:我们定义一个静态方法get_instance,去实现一个单实例的方式

class Foo(object):
    instance = None  #初始化一个对象

    def __init__(self):
        self.name = 'alex'

    @classmethod
    def get_instance(cls):
        if Foo.instance:  #如果对象已经存在,就直接返回这个对象
            return Foo.instance
        else:  #不存在就创建一个新的对象
            Foo.instance = Foo()
            return Foo.instance

    def process(self):
        return '123'

obj1 = Foo.get_instance()
print(id(obj1))
obj2 = Foo.get_instance()
print(id(obj2))

#输出
2483145426760
2483145426760

以上这种还是比较low的,我们还需要通过定义静态方法来搞定。

3.2、重写new方法实现

说明:我们知道一个创建一个对象,先执行 它的 __new__方法  ,再去执行 __init__方法,所以我们重写new方法即可

class Foo(object):
    instance = None  #初始化一个对象

    def __init__(self):
        self.name = 'alex'

    def __new__(cls, *args, **kwargs):
        if Foo.instance:  #如果对象已经存在,就直接返回这个对象
            return Foo.instance
        else:  #不存在就创建一个新的对象
            Foo.instance = object.__new__(cls, *args, **kwargs)
            return Foo.instance

    def process(self):
        return '123'

obj1 = Foo() 
print(obj1)
obj2 = Foo()
print(obj2)

#输出
<__main__.Foo object at 0x00000156A41D4748>
<__main__.Foo object at 0x00000156A41D4748>

3.3、抄袭武sir的写法

class Foo(object):
    __instance = None  #初始化一个对象

    def __init__(self):
        self.name = 'alex'

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            obj = object.__new__(cls, *args, **kwargs)
            cls.__instance = obj
        return cls.__instance
    
    def process(self):
        return '123'

obj1 = Foo()
print(obj1)
obj2 = Foo()
print(obj2)

#输出
<__main__.Foo object at 0x00000230DA454748>
<__main__.Foo object at 0x00000230DA454748>

四、总结

KindEditor编辑器:

  1、beautifulsoup4 对标签进行过滤

  2、单实例模式 => 永远用一个对象的实例

posted @ 2018-05-23 10:28  帅丶高高  阅读(213)  评论(0编辑  收藏  举报