python - Flask中的用户确认问题
ringa_lee
ringa_lee 2017-04-18 09:55:31
0
1
399

在学习Flask-Web开发这本书的第八章遇到了问题,就是在数据库模型中添加确认用户账户的功能时,有这样一段代码:

class User(UserMixin,db.Model):

__tablename__ = 'users'
id = db.Column(db.Integer,primary_key=True)
email = db.Column(db.String(64),unique=True,index=True)
username=db.Column(db.String(64),unique=True,index=True)
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128))
confirmed = db.Column(db.Boolean,default=False)

@property
def password(self):
    raise AttributeError('password is not a readable attribute.')

@password.setter
def password(self,password):
    self.password_hash =generate_password_hash(password)

def verify_password(self,password):
    return check_password_hash(self.password_hash,password)

def generate_confirmation_token(self,expiration=3600):
    s=Serializer(current_app.config['SECRET_KEY'],expiration)
    return s.dumps({'confirm':self.id})

def confirm(self,token):
    s=Serializer(current_app.config['SECRET_KEY'])
    try:
        data=s.loads(token)
    except:
        return False 
    if data.get("confirm") != self.id:
        return False
    self.confirmed = True
    db.session.add(self)
    db.session.commit()
    return True

def __repr__(self):
    return '<User %r>' % self.username

confirm()方法验证令牌。
其中,有一段是这样的:if data.get("confirm") != self.id,正常情况下data返回的不就是原数据么({'confirm':self.id}),加这段代码的意义是什么
书中有解释:confirm()方法还检查令牌中的id是否和存储在current_user中的已登录用户匹配。这里的current_user是否就是指正在进行验证的这个用户?对于Flask来说,尚未确认的用户也算已登录的用户吗,即current_user.is_authentiacated为True。将代码改为

          if data.get("confirm") != current_user.get_id():

可否?

以及最后一句话,添加这段代码:if data.get("confirm") != self.id,即使恶意用户知道如何生成签名令牌,也无法确认别人的账户。账户应该是指注册或者登录时的email吧,这段代码确认了confirm数据是否为用户唯一id号,和用户账户(email)有什么关系

ringa_lee
ringa_lee

ringa_lee

全部回覆(1)
Ty80
def confirm(self,token):
    s=Serializer(current_app.config['SECRET_KEY'])
    try:
        data=s.loads(token)
    except:
        return False 
    if data.get("confirm") != self.id:
        return False
    self.confirmed = True
    db.session.add(self)
    db.session.commit()
    return True
    

要注意的是這裡的tokenSECRET_KEY

這裡的data經過了一次data=s.loads(token),如果token和SECRET_KEY不正确的话,get得到的id也是不正確的,這樣就起到了驗證的作用。

這裡的帳號指的是每個帳號自己的id,就算惡意使用者成功偽造了token,因為使用者的id號不正確,這裡無法成功驗證。

登入和確認是兩個屬性,這兩個之間沒有耦合的關係,沒有登入的帳號也可以是確認過的,所以沒有確認的帳號也可以是登入狀態的。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!