一、框架
OpenStack Restful API开发框架为Paste +PasteDeploy +Routes +Webob:
(1)Paste +PasteDeploy:负责构建WSGI Server和Application;
(2)Routes:负责完成URL路由转发;
(3)Webob:负责封装WSGI请求和响应。
Restful API程序的主要特点就是URL_PATH会与功能对应起来,Routes的URL路由功能负责URL_PATH对应了哪些功能和实现了哪些功能。
二、WSGI入口:
(1)wsgi-keystone.conf
文件路径:/etc/httpd/conf.d/wsgi-keystone.conf
功能:文件中定义了两个虚拟主机端口:5000和35357,可以根据用户请求URL_PATH中端口的不同来指定使用哪一个虚拟主机端口的WSGI Application来处理这个请求;
(2)wsgi.py
文件路径:/usr/lib/python2.7/site-packages/keystone/server/ wsgi.py
方法名:initialize_application
l keystone_service.loadapp()函数内部调用了paste.deploy.loadapp()函数来加载WSGI Application,至于如何加载由Paste的配置文件keystone-paste.ini来决定;
l config.find_paste_config()用来查找并加载需要用到的Paste配置文件;
l name是用来确定application入口的,表示配置文件keystone-paste.ini中一个composite section的名字,在Keystone的paste.ini 中,请求必须先由[composite:main]或者[composite:admin]处理,所以在keystone项目中,name的值必须是main或者admin。
三、keystone-paste.ini配置文件
(1)首先根据wsgi.py程序中的name值确定由哪个composite来处理,假设这里的name值为admin;
(2)以http://controller:35357/v3/auth/tokens为例,在这一步paste会将该请求路由给api_v3处理(处理/v3)
(3)pipeline用来存放一系列的filter过滤器和app
l http请求会从pipeline第一个section开始处理,一直向后传递直到结束;
l pipeline中最后一个section对应的一定是一个app类型的section;(service_v3是一个app)
l pipeline中除最后一个section之外的所有section一定是一个filter类型的section
(4)filter用于过滤请求和响应,以HealthCheck为例:
(5)service_v3是实现主要功能的具体的WSGI Application(处理/auth/tokens),这里将请求转移到了v3_app_factory 这个函数上,routes 会创建一个 mapper 对象,然后调用该 Mapper对象的connect方法把 URL_Path(这里是/auth/tokens )映射到一个具体的controller的某个action上。
四、处理/auth/tokens请求
Keystone服务将每个功能都分到单独的目录下每个目录下都包含了routers.py、controllers.py、core.py这三个文件,下面以处理/auth/tokens请求为例:
Step1:找到token相关的功能下的router
(1)文件路径:/usr/lib/python2.7/site-packages/keystone/token/routers.py
(2)找到Router类下的append_v3_routers方法,从append_v3_routers方法中看出,对应的controller为controllers.auth()这个方法,/auth/tokens 对应的post的action为authenticate;
Step2:找到对应的controller
(1)文件路径:/usr/lib/python2.7/site-packages/keystone/token/controllers.py
(2)因为是采用了本地用户名和密码认证,找到LocalAuthenticatioMethod类下的authenticate方法
在这个方法中,引入了用户名和密码进行有效性校验,首先通过identify_api.get_use_by_name获取用户信息,之后再通过identify_api.authenticate来验证用户名和密码。
Step3:找到identify_api
(1)文件路径:/usr/lib/python2.7/site-packages/keystone/identify/core.py
(2)找到core.py文件中Manager类中的authenticate方法
从这个方法中看出此处使用了drive继续进行认证。
Step4:找drive
(1)文件路径:/usr/lib/python2.7/site-packages/keystone/identify/sql.py,在keystone.conf文件中配置
[identity]
# driver = keystone.identity.backends.sql.Identity
(2)找到sql.py文件中Identify类中的authenticate方法,这里的session是实际连接Mysql数据库的session. 使用session取出user表所对应的信息。然后使用_check_password进行密码的校验。在看密码校验前,我们先看看user表所对应的结构:
这里使用session取出了sql数据库中user对应的信息,再使用_check_password进行密码校验,数据库中的user表所对应的结构如下:
(3)找到Identify类下面的_check_password方法
这里又使用了password_hashing中的check_password方法继续校验;
Step5:check_password方法
(1)文件路径:/usr/lib/python2.7/site-packages/keystone/common/password_hashing.py
(2)对密码进行加密校验,
Step6:校验完密码之后,将结果再一级一级原路返回到wsgi.py中的Application类中_call_方法中来响应http请求
(1)文件路径:/usr/lib/python2.7/site-packages/keystone/common/wsgi.py
(2)请求响应最后由在wsgi.py文件中的Application类下的_call_方法返回;
(3)_call_方法中调用了render_response方法,转化body格式,返回给client。
五、小结
keystone认证过程可以分为五层:中间件层(middlewares)、路由层(routers)、控制器层(controllers)、数据管理层(Manager)、后台数据层(mariadb、memcached等)。中间层主要完成一些共用的功能(如请求报文的内容格式、大小等检查);路由层主要将请求映射到相应的controller和action;控制层是负责实现action的具体逻辑方法;数据管理层建立了对外一致接口为控制层提供数据服务;后台数据层主要是存放keystone相关数据。
在keystone数据中有如下数据表: