flask_security学习笔记

高山
2023-12-01

flask_security学习笔记

记录一下使用flask_security过程中遇到的一些坑。

1、覆盖默认页面(template)

在templates文件夹中创建security文件夹,创建要替换的同名html文件即可。

2、覆盖默认form

创建Form对象,(最好继承自flask_security默认的Form,默认给提供了很多表单验证方法。)在创建Security对象时指明即可,如下:

				security = Security(
							app,  user_datastore,
		                	confirm_register_form=ExtendConfirmRegisterForm,
		                	login_form=ExtendLoginForm,
		               	    reset_password_form=ExtendResetPasswordForm,
		                	forgot_password_form=ExtendForgetPasswordForm,
		                	change_password_form=ExtendChangePasswordForm
                      )

注意:
1、需要邮箱认证的注册表单和不需要邮箱认证的注册表单不同。confirm_register_form,register_form。

2、默认的ForgotPasswordForm的email字段(StringField)有一个验证器(validator)名为valid_user_email,这个验证器会根据邮箱值(账号)查询数据库,验证用户输入的账号(邮箱)是否存在,将结果赋值给form.user。默认ForgotPasswordForm还自定义了一个validate,

def validate(self):
	    if not super(ForgotPasswordForm, self).validate():
	        return False
	    if requires_confirmation(self.user):
	        self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
	        return False
	    return True

requires_confirmation方法需要参数self.user这个值是valid_user_email验证成功(此账号存在)后得到的。
如果你自定义一个ForgotPasswordForm虽然继承了默认的ForgotPasswordForm。但是你要是覆盖默认的email字段的话,此StringField对象没有valid_user_email。所以不会给self.user赋值,在调用requires_confirmation时,会报错。
错误信息如下:

File "/home/sheng/.local/lib/python3.6/site-packages/flask_security/confirmable.py", line 63, in requires_confirmation
    user.confirmed_at is None)
AttributeError: 'NoneType' object has no attribute 'confirmed_at'

解决方法:
1、从flask_security.forms中import该验证器valid_user_email,添加至自定义的email字段(StringField对象)的validators属性中。
2、使用默认的email字段

3、roles_required验证失败后跳转页面修改(默认登录页面)

方法一:配置SECURITY_UNAUTHORIZED_VIEW = lambda :’/unauthorized’,不能是字符串,/unauthorized是url,需要自定义视图函数。
方法二:装饰器@security.unauthorized_handler

4、login_required验证失败后默认跳转页面修改(默认是登录页面)

3 中的方法无法修改默认的login_required验证失败跳转的页面。login_required是flask_login中的用于用户登录验证的装饰器。我们需要用LoginManager对象的unauthorized_handler装饰器。flask_security会为当前app对象添加login_manager对象,我们可以这样使用:

    @app.login_manager.unauthorized_handler
	def unauthorized():
    	abort(403)

security对象中有当前app对象,你也可以这样使用:

	@security.app.login_manager.unauthorized_handler
	def unauthorized():
    	abort(403)

5、发送邮件

如果Message对象中没有指明发送者(sender),需要配置默认的发送者(SECURITY_EMAIL_SENDER),不然会报错:

File "/home/sheng/anaconda3/envs/chatbot/lib/python3.7/site-packages/flask_mail.py", line 105, in sanitize_address
    nm, addr = addr
ValueError: too many values to unpack (expected 2)

6、用户追踪

需设置SECURITY_TRACKABLE = True
User类需要添加如下字段(字段名必须如下所示):

    last_login_at = DateTimeField()
	current_login_at = DateTimeField()
	last_login_ip = StringField()
	current_login_ip = StringField()
	login_count = IntField(default=0)

注意: 需要修改配置SECURITY_DATETIME_FACTORY 为datetime.datetime.now,默认为datetime.datetime.utcnow返回的是UTC(协调世界时即格林威治平太阳时间,标准时间)时间,与北京时间相差8小时。

 类似资料: