飞哥的海

导航

Flask登录初探

0.python能干啥,首先就是让小学生学编程啊。接续上篇,为了实现前后端登录打通,开始搭建后端相关

1.python装起来,考虑使用前后端分离,那么就用Flask框架

2.Flask装起来,按照Flask官网,他推荐只用虚拟机来运行flask程序,这是蛮好的思路,已阅,推广之。(https://dormousehole.readthedocs.io/en/latest/installation.html#installation)

3.首先安装虚拟环境,找个文件夹在其内运行CMD命令:py -m venv venv 命令执行完毕后,就会在此文件夹下生成venv子文件夹,里面有一堆文件。

4.运行venv目录下的scripts目录下的activate。即:venv\scripts\activate.如下图所示。(其实对于任何py程序都可以如此创建虚拟环境,不需要改任何字符。习惯这么模式后,看到venv就知道是在虚拟环境下运行)

 

 5.就在虚拟环境目录下,运行pip install Flask。注意不要在其他目录下运行,否则虚拟环境白搞了。

 

 6.照这教程敲一波代码,体会一下Flask的洪荒之力 https://dormousehole.readthedocs.io/en/latest/quickstart.html#quickstart

7.经过七七四十九天,五行代码敲击完毕。准备运行

8.注意在powershell和cmd两种命令行 指令有点不一样。

  8.1 在cmd下是这样的:

  set FLASK_APP=hello.py
  flask run

  8.2 在powershell下是这样的:

  $env:FLASK_APP = "hello.py"
  flask run

9.运行后,效果

 

 10.浏览器中打开网址,就能看到东西了。

------------------------------------------------------------------------------------------------------------------------

0.上一波是初试Flask,这一波进入主题,走一个登录

1.如下图全部代码

  

 2.红框圈出的,是生成secretKey的方法,在cmd下运行红框中的代码,将其copy到secretKey即可。如果忽略secretKey,那么在使用session时,python就会提示 "session不可用因为没有使用secertKey",其实就是用来加密cookie的。

 3.flask run 之后,就会展现下列效果

 

 

4.到此为止,简单实现了登录过程。并且使用了flask提供的session模块,如果把session.clear注销,将能实现记住登录用户的功能。

5.当然一个登录,需要有数据库交互,还要和前端做关联。下面暂时使用 用户 列表,来实现登录验证

 

 6.改造了两部分,一个是添加了USERS列表。第二个是在helloworld函数内添加用户合法性验证代码。

需要注意的是。我这里使用了generate_password_hash函数用于生成密码的散列值,密码明文存储这是大忌。

另外这个散列函数会有salt值,这会导致每次用相同密码产生的散列值是不一样的。所以只能使用check_password_hash 来判定密码是否一致。具体加salt实现原理,自己看源码吧。

 

 

 7.把USERS列表用数据库替代,就实现了真正意义上的用户登录。把vue前端和本后端代码关联暂缓实现,再次深入登录过程,尝试使用Flask_login组件,来重构上述过程。之后再对jwt做个demo。

------------------------------------------------------------------------------------------------------------------

0.第三波强烈来袭,用flask_login走一波上述逻辑 ,老规矩 祭出官网 镇住bug (https://flask-login.readthedocs.io/en/latest/index.html)。

有一点要注意,flask_login有个中文站点,比英文主站版本要低,可以结合对照看,但小部分内容不一样。注意识别。

1.pip install flask-login 用这句话把其装起来,当然要在虚拟机venv下安装了。千万别忘啦。

2.根据官网步骤是能完全搞出来的。我在这里多嘴简化一下。flask_login 只需套着来就行,

  先添加这两行代码 login_manager = LoginManager() 

           login_manager.init_app(app)

  然后实现user 类。可以由UserMixin继承获得。这个user类必须实现,别问为什么。学渣没有资格问为什么,抄就行了。

    还要把这块代码放进来 @login_manager.user_loader
            def load_user(user_id):
              return User.get(user_id)

  最后,在需要登录验证的函数上加 注解 @login_required 

3.大致流程就是这样。正式走一遍代码。看我这个学渣能不能抄明白。

from flask import Flask,session,redirect,url_for,request
from werkzeug.security import generate_password_hash,check_password_hash
from flask_login import LoginManager,login_user,logout_user,login_required,current_user
from user import User,USERS

app = Flask(__name__)
app.secret_key=b'\x12\xb6\xc0\xdd6^!\xf9\x9b\x83\x95G\x93K_9' 
#python -c "import os; print(os.urandom(16))"

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'default'

@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)

@app.route('/login2', methods=['GET', 'POST'])
def login2():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        user = User.queryUser(username)
        if (user != None) and (user.verifyPassword(password)) :
            login_user(user)
            return "hello flaskLogin:{}@{} ".format(username, password)
        else:
            return " username or password is not correct"
    else:
        return '''
            <form method="post">
                <p><input type=text name=username>
                <p><input type=password name=password>
                <p><input type=submit value=Login>
            </form>
        '''

@app.route("/logout2")
@login_required
def logout2():
    logout_user()
    return 'bye bye '

@app.route('/index')
@login_required
def index():
    return '我爱你 祖国 (来自' + current_user.username +'的心声)'

@app.route('/default')
def default():
    return '祖国万岁(请使用login2登录)'

@app.route('/')
def hello_world():
    if session.get('username') == None :
        return redirect(url_for('login'))
    else:
        username = session.get('username') 
        password = session.get('password') 
        #session.clear()
        for user in USERS:
            if (user.get("name") == username) and (check_password_hash(user.get("password"),password)):
                return " hello world:{}@{} ".format(username, password)  
          
        return " username or password is not correct"


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        session['password'] = request.form['password']
        return redirect(url_for('hello_world'))
    else:
        return '''
            <form method="post">
                <p><input type=text name=username>
                <p><input type=password name=password>
                <p><input type=submit value=Login>
            </form>
        '''

@app.route('/logout')
def logout():
    session.pop('username')
    session.pop('password')
    return 'bye bye'

User.py

from flask_login import UserMixin
from werkzeug.security import check_password_hash, generate_password_hash


USERS = [
    {
        "id":1,
        "name":"admin",
        "password":generate_password_hash('123')
    },
    {
        "id":2,
        "name":"李四",
        "password":generate_password_hash('123')
    },    
]
 
class User(UserMixin):
    def __init__(self,user):
        self.username = user.get("name")
        self.password_hash = user.get("password")
        self.id = user.get("id")


    @staticmethod
    def queryUser(username):
        for user in USERS:
            if (user.get('name') == username) :
                return User(user)
        return None
    
    def verifyPassword(self,password):
        if self.password_hash is None:
            return False
        return check_password_hash(self.password_hash,password)

    def get_id(self):
        return self.id

    def get(user_id):
        print('get(user_id):'+str(user_id))
        print('get(user_id):'+str(type(user_id)))
        if not user_id:
            print('if not user_id:')
            return None
        for user in USERS:
            print('user.get("id"):' + str(user.get('id')))
            print('user.get("id"):' + str(type(user.get('id'))))
            if str(user.get('id')) == str(user_id) :
                print('User(user)')
                return User(user)
        print('None')
        return None

 

4.上述代码,执行效果如下:

 

 

 

 

 

 

 

 

 

 

 

 5.从登录到鉴权到注销用户。这一套基本体系已经构建完毕。当然flasklogin还有不少小技能需要挖掘。

posted on 2020-07-02 11:11  飞哥的海  阅读(480)  评论(0编辑  收藏  举报