简单示例 flask-login 基于 request_loader 方法的 token 登录

效果图: 



Flask-Login is a Flask extension that provides a framework for handling user authentication.This post will give you a basic tutorial of the Flask-Login mechanism for token based authentication.

The goal of this post is to give a very basic introduction to token based authentication using Flask-Login.Usually the user credentials are stored in a database, with passwords hashed. However the authenticationmechanism can be understood without having to worry about database, and various token generation algorithms.As a first step lets focus on just understanding the authentication mechanism. Then in a subsequent postwe will handle other important parts.

To run this example, you will need flask and flask-login with their dependencies installed.This can be done usingpip as shown below:

>pip install flask
>pip install flask-login

Example Code

Here is the full source code that we are about to discuss:

# Author: Gouthaman Balaraman

# http://gouthamanbalaraman.com/minimal-flask-login-example.html



from flask import Flask, Response

from flask.ext.login import LoginManager, UserMixin, login_required

app = Flask(__name__)

login_manager = LoginManager()

login_manager.init_app(app)

class User(UserMixin):

# proxy for a database of users

     user_database = {"JohnDoe": ("JohnDoe","John"),

                             "JaneDoe": ("JaneDoe","Jane")}

    def __init__(self,username,password):

        self.id = username

        self.password = password



    @classmethod

    def get(cls,id):

        return cls.user_database.get(id)

@login_manager.request_loader

def load_user(request):

    token = request.headers.get('Authorization')

    if token is None:

        token = request.args.get('token')

    if token is not None:

        username,password = token.split(":")# naive token

        user_entry = User.get(username)

        if (user_entry is not None):

             user = User(user_entry[0],user_entry[1])

            if (user.password == password):

            return user

    return None




@app.route("/",methods=["GET"])

def index():

        return Response(response="Hello World!",status=200)


@app.route("/protected/",methods=["GET"])

@login_required

def protected():

    return Response(response="Hello Protected World!",status=200)


if __name__ == '__main__':

    app.config["SECRET_KEY"]="ITSASECRET"

    app.run(port=5000,debug=True)




view raw flask_login_token.py hosted with ❤ by GitHub

Code Explained

Lets delve deeper into this example, and I will explain each part of the code in greater detail here.

from flask import Flask, Response
from flask.ext.login import LoginManager, UserMixin, login_required

app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)


The first five lines of the code import the required modules, and initializes the Flaskapp. ThentheLoginManager instance is created and then is configure for login. Now lets try to understandtheUser class.

class User(UserMixin):
    # proxy for a database of users
    user_database = {"JohnDoe": ("JohnDoe", "John"),
               "JaneDoe": ("JaneDoe", "Jane")}

    def __init__(self, username, password):
        self.id = username
        self.password = password

    @classmethod
    def get(cls,id):
        return cls.user_database.get(id)

Here I have created the User class by overloading theUserMixin class. TheUserMixin classimplements some of the default methods, and hence is a convenient starting point. Thedictuser_databaseis a proxy for all the database code one would need. I am abstracting this away as adict for simplicity.Theget class method returns the user data fromuser_database.

For the LoginManager to handle authentication, we have to provide a method for it to load user.Here I use the generic@login_manager.request_loader decorator to decorate theload_user function.The expected behavior of a request_loader is to return aUser instance if the provided credentials arevalid, and returnNone otherwise.

@login_manager.request_loader
def load_user(request):
    token = request.headers.get('Authorization')
    if token is None:
        token = request.args.get('token')

    if token is not None:
        username,password = token.split(":") # naive token
        user_entry = User.get(username)
        if (user_entry is not None):
            user = User(user_entry[0],user_entry[1])
            if (user.password == password):
                return user
    return None

The load_user looks for a token in Authorization header, or the request arguments. If a tokenis provided, then I return an instance ofUser if the token is valid, and returnNone otherwise.Here I assume that a valid token would be of the form<username>:<password>. This is a naive token,and should not be used in practice. Using serializers fromitsdangerous package can come handy. Wewill touch upon these issues in another post.

Once this setup is done, in order to require authentication for a route, use the@login_requireddecorator.

Run the above script, and if you visit the LocalHostUnAuthenticated route withouta token you will get a 401 Unauthorized message. If you pass a token toLocalHostAuthenticated, then you will be allowed access to the protected page.

Conclusion

This article explained how to write token based authentication using Flask-Login extension. The focusof this article was explaining the basic workings offlask-login without having to setup database oreven the token generation. Once the basic plumbing is setup, one can extend this example in two ways:




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值