flask_openid多节点下登录问题

应用场景

在web开发中,不可避免使用openid来进行登录。当使用flask框架开发时,flask_openid则是在openid的基础上进行封装,使其更适用于flask框架。flask_openid的官方文档demo是使用fs_store_path来存储临时文件,例如assoc的各个信息,详情可以看openid的登录流程。
demo的代码如下

from flask.ext.openid import OpenID
oid = OpenID(app, '/path/to/store', safe_roots=[])

在单机开发下,按着官方文档进行发开是没有啥问题的。但是当代码部署到多节点的服务器上时,则会遇到多节点问题。

问题描述

多节点下登录的流程如下:
1 A节点发起openid请求,获得assoc信息,并保存在本节点的保存文件中。
2 A节点发起跳转,跳转到openid的验证页面,用户进行验证操作。
3 验证成功后,跳转到发情openid验证请求的网站,但由于此时服务器是多节点,所有不能保证验证成功的响应能跳转到A节点。假如跳转到了B节点,则验证失败。

通过上述的分析发现在多节点服务器中,不能用本地化文件的方式来保存获得的assoc信息,必须要使用其他方式。

问题解决方法

仔细查看flask_openid的官方文档,其中

oid = OpenID()

def create_app():
    app = Flask(__name__)
    oid.init_app(app)
    return app
Parameters:	
	app – the application to register this openid controller with.
	fs_store_path – if given this is the name of a folder where the OpenID auth process can store temporary information. If neither is provided a temporary folder is assumed. This is overridden by the OPENID_FS_STORE_PATH configuration key.
	store_factory – alternatively a function that creates a python-openid store object.
	fallback_endpoint – optionally a string with the name of an URL endpoint the user should be redirected to if the HTTP referrer is unreliable. By default the user is redirected back to the application’s index in that case.
	extension_responses – a list of OpenID Extensions Response class.
	safe_roots – a list of trust roots to support returning to
	url_root_as_trust_root – whether to use the url_root as trust_root

其中store_factory 便是解决方法,alternatively a function that creates a python-openid store objec意思是一个函数提供python-openid store对象,于是便回到python-openid 源码中分析。
经过分析,可以发现python openid中有store.sqlstore.MySQLStore,用来将assoc信息存放在mysql数据库中,从而解决多节点下assoc信息同步问题。其中store.sqlstore.MySQLStore代码如下:

  def __init__(self, conn, associations_table=None, nonces_table=None):
 	    self.conn = conn
        self.cur = None
        self._statement_cache = {}
        self._table_names = {
            'associations': associations_table or self.associations_table,
            'nonces': nonces_table or self.nonces_table,
            }
        self.max_nonce_age = 6 * 60 * 60 # Six hours, in seconds

只要按着这个初始化便可,如果有不明白,可以去查看源码。

解决方案详情

from openid.store import sqlstore
from flask_openid import OpenID
oid = OpenID()
mysql_config = app_config['mysql']
conn = MySQLdb.connect(host=mysql_config['host'], user=mysql_config['user'], 	
					   passwd=mysql_config['password'],
                       db=mysql_config['db'], port=mysql_config['port'], charset='utf8')
oid.store_factory = lambda: sqlstore.MySQLStore(conn)

其中 lambda: sqlstore.MySQLStore(conn)的作用是因为oid.store_factory需要的是函数,所有用lambda表达式来封装并返回MySQLStore,当然,你也可以自己写一个函数不用lambda表达式。

版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/aizenggege/article/details/82845373

你可能感兴趣的:(python,Web开发,flask,openid)