2021SC@SDUSC
在大致学习了jijan2的基本用法后,便开始了wsgidav的源码分析。WsgiDAV 是一个用 Python 开发的通用 WebDAV 服务器,基于 WSGI 运行,支持 SSL。
wsgidav安装和运行:
$ pip install wsgidav
$ wsgidav --host=0.0.0.0 --port=8080 --root=/tmp
WARNING: share '/' will allow anonymous access.
Running WsgiDAV/2.2.1 CherryPy/unknown Python/3.5.2
Serving on http://0.0.0.0:8080 ...
打开wsgidav可以发现里面包含几个主要的文件夹,分别负责不同的功能。
wsgidav结构:
分析dc文件夹,进入以后查看base_dc.py。域控制器的抽象基类(由HTTPAuthenticator使用)。这个ABC作为DomainControllers的基类,并提供了一些默认实现。域控制器可以向“环境”添加条目["wsgidav.auth. ..."]]“名称空间,以便为下列中间件定义访问权限(例如dir_browser)和DAV提供程序。
base_dc.py主要包含了一个名叫BaseDomainController的类。
类中主要方法:
def __init__(self, wsgidav_app, config)
def __str__(self)
def _calc_realm_from_path_provider(self, path_info, environ)
def get_domain_realm(self, path_info, environ)
def require_authentication(self, realm, environ)
def is_share_anonymous(self, path_info)
def basic_auth_user(self, realm, user_name, password, environ)
def supports_http_digest_auth(self)
def _compute_http_digest_a1(self, realm, user_name, password)
def digest_auth_user(self, realm, user_name, environ)
def __init__(self, wsgidav_app, config)是类的初始化,def __str__(self)是获取自身类名的函数
def __init__(self, wsgidav_app, config):
self.wsgidav_app = wsgidav_app
self.config = config
def __str__(self):
return "{}()".format(self.__class__.__name__)
def _calc_realm_from_path_provider(self, path_info, environ):派生类实现get_domain_realm()的内部辅助函数。
if environ:
# Called while in a request:
# We don't get the share from the path_info here: it was already
# resolved and stripped by the request_resolver
dav_provider = environ["wsgidav.provider"]
else:
# Called on start-up with the share root URL
_share, dav_provider = self.wsgidav_app.resolve_provider(path_info)
if not dav_provider:
logger.warn(
"_calc_realm_from_path_provider('{}'): '{}'".format(
util.safe_re_encode(path_info, sys.stdout.encoding), None
)
)
return None
realm = dav_provider.share_path
if realm == "":
realm = "/"
return realm
def get_domain_realm(self,path_info,environ):主要是返回给定URL的规范化领域名称。
@abc.abstractmethod
def get_domain_realm(self, path_info, environ):
raise NotImplementedError
def require_authentication(self,realm,environ):返回False以禁用此请求的身份验证。
这个方法被调用—在启动时,检查给定共享是否允许匿名访问。
在本例中,' environ '为None。对于每个请求,在基本或摘要身份验证被处理之前。如果返回False,我们也可以设置环境变量
匿名访问:[" wsgidav.auth环境。= (,…)[" wsgidav.auth环境。权限" = (,…),返回假
参数:领域(str):environ (dict | None):
返回:False,允许匿名访问,true强制后续摘要或基本身份验证
def require_authentication(self, realm, environ):
raise NotImplementedError
def is_share_anonymoue(self,path_info):如果共享路径被授予匿名访问权限,则返回true,否则返回false
def is_share_anonymous(self, path_info):
realm = self.get_domain_realm(path_info, None)
return not self.require_authentication(realm, None)
def basic_auth_user(self,realm,user_name,password,environ):
检查realm/user_name/password的请求访问权限。由http_authenticator调用用于基本身份验证请求。
参数:领域(str):user_name (str):密码(str):环境(dict类型):
返回:如果用户未知或未经授权,则为False,如果用户被授权,则为True
def basic_auth_user(self, realm, user_name, password, environ):
raise NotImplementedError
def supports_http_digest_auth(self):提示该DC实例是否支持HTTP摘要身份验证主题。如果为真,' HTTPAuthenticator '将调用' dc.digest_auth_user() '所以这个方法也必须实现。
def supports_http_digest_auth(self):
raise NotImplementedError
def _compute_http_digest_a1(self,realm,user_name,password):用于派生类计算摘要哈希的内部帮助程序(A1部分)
def _compute_http_digest_a1(self, realm, user_name, password):
data = user_name + ":" + realm + ":" + password
A1 = md5(compat.to_bytes(data)).hexdigest()
return A1
def digest_auth_user(self,realm,user_name,environ):检查realm/user_name的访问权限。由http_authenticator调用用于基本身份验证请求。计算HTTP摘要哈希A1部分。任何为' supports_http_digest_auth() '返回true的域控制器,必须实现此方法。
参数:领域(str):user_name (str):环境(dict类型):
返回:str: MD5 (" {usern_name}:{领域}:{密码}”),如果用户未知或被拒绝,则为false
def digest_auth_user(self, realm, user_name, environ):
raise NotImplementedError
到此,BaseDomainController代码分析完成,在分析源码初期,由于对于各种知识了解存在欠缺,分析过程总会遇到不了解的名词或代码,需要查询各种资料,代码分析较为缓慢,后面分析速度应该会逐渐提高。