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、单实例模式 => 永远用一个对象的实例