You can use the Flask-Login module to do access control. It provides user session management for Flask: logging in, logging out, and remembering session.

The module stores the user ID, restricts views to logged in users, protects cookies and has many other features.

Related course: Python Flask: Create Web Apps with Flask

Install module

The Flask-login module we use is.

1
Flask-Login==0.3.2

so install directly by using pip installation:

1
pip install Flask-Login==0.3.2

Flask-Login

The Flask-Login uses the Flask-MongoEngine of the previous article. So we still need to bind with the server at the beginning:

1
2
3
from flask.ext.login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app)

This will bind the Flask-Login to the server. However, this does not seem to have any effect.

First, what is the URL of the landing?

This does not have a default login URL in the Flask-Login, so we need to specify:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask.ext.login import login_user
login_manager.login_view = 'login'

@app.route('/login', methods=['POST'])
def login():
info = json.loads(request.data)
username = info.get('username', 'guest')
password = info.get('password', '')
user = User.objects(name=username,
password=password).first()
if user:
login_user(user)
return jsonify(user.to_json())
else:
return jsonify({"status": 401,
"reason": "Username or Password Error"})

There are actually two things:

  • with the code logic of login_view written 'login',
  • define login_view: tell Flask the URL of the landing that we are dealing with
1
login_manager.login_view = 'login'

Here we define the login_view ‘login’.

How did Flask find the location of our login logic based on the login?

We defined it:

1
def login(self, xxx)

This function, and then it’s where we deal with the login logic code.

So what is the code for user login? It’s this:

1
login_user(user)

This statement sets the status of the current user to be logged in. There is no in-depth explanation here, you just need to know that when the function is called, the state of the user is the login state.

Related course: Python Flask: Create Web Apps with Flask

User Model

Well, now the problem is, next time you have a request, how do we know if there is a user landing, how do we know which user is it?

At this time, we will find that our Model is not perfect enough, and we need to improve the Model.It should be improved in this way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User(db.Document):   
name = db.StringField()
password = db.StringField()
email = db.StringField()
def to_json(self):
return {"name": self.name,
"email": self.email}

def is_authenticated(self):
return True

def is_active(self):
return True

def is_anonymous(self):
return False

def get_id(self):
return str(self.id)

We can see that there are two additional approaches here, which are:

  • is_authenticated: The current user is authorized because we can operate when we log on, so the default is the authorized

  • is_anonymous: it is obvious that if the current user is anonymous, it must not be

  • is_active: for judging whether the current user has been activated, the activated user can log on to

  • get_id: returns the id. But we still cannot know who the current login user is, so we also need to tell Flask-Login how to obtain the user’s method through an id:

1
2
3
@login_manager.user_loader
def load_user(user_id):
return User.objects(id=user_id).first()

By specifying user_loader, we can query who the current login user is.In this way, we will judge whether the user can login or not.

We need to take control of landing page rights. We set up the REST API to increase, delete and modify to use for the login. Only the API of the query can be easily visible.

The method for controlling landing urls is simple,add one decorator with @login_required. So:

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask.ext.login import login_required
@app.route('/', methods=['PUT'])
@login_required
def create_record():
......
@app.route('/', methods=['POST'])
@login_required
def update_record():
......
@app.route('/', methods=['DELETE'])
@login_required
def delte_record():
......

This limits the increase, modify, and delete HTTP operations to be user-enabled.

After login, the user should also be able to logout. The code is as follows:

1
2
3
4
5
6
from flask.ext.login import logout_user
@app.route('/logout', methods=['POST'])
def logout():
logout_user()
return jsonify(**{'result': 200,
'data': {'message': 'logout success'}})

Here, a logout_user() method was called from logout().

You should check if the user was logged in, in the first place:

1
2
3
4
5
6
7
8
9
10
from flask.ext.login import current_user
@app.route('/user_info', methods=['POST'])
def user_info():
if current_user.is_authenticated:
resp = {"result": 200,
"data": current_user.to_json()}
else:
resp = {"result": 401,
"data": {"message": "user no login"}}
return jsonify(**resp)

If you log on, then current_user is the object of User, then the to_json method can return the user information of the current login user, so that we can write an API for obtaining user information.

Example

The complete code for this chapter is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python
# encoding: utf-8
import json
from flask import Flask, request, jsonify
from flask.ext.login import (current_user, LoginManager,
login_user, logout_user,
login_required)
from flask_mongoengine import MongoEngine
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
'db': 'your_database',
'host': 'localhost',
'port': 27017
}
app.secret_key = 'some key'
db = MongoEngine()
login_manager = LoginManager()
db.init_app(app)
login_manager.init_app(app)
login_manager.login_view = 'login'
@login_manager.user_loader
def load_user(user_id):
return User.objects(id=user_id).first()
@app.route('/login', methods=['POST'])
def login():
info = json.loads(request.data)
username = info.get('username', 'guest')
password = info.get('password', '')
user = User.objects(name=username,
password=password).first()
if user:
login_user(user)
return jsonify(user.to_json())
else:
return jsonify({"status": 401,
"reason": "Username or Password Error"})
@app.route('/logout', methods=['POST'])
def logout():
logout_user()
return jsonify(**{'result': 200,
'data': {'message': 'logout success'}})
@app.route('/user_info', methods=['POST'])
def user_info():
if current_user.is_authenticated:
resp = {"result": 200,
"data": current_user.to_json()}
else:
resp = {"result": 401,
"data": {"message": "user no login"}}
return jsonify(**resp)
class User(db.Document):
name = db.StringField()
password = db.StringField()
email = db.StringField()
def to_json(self):
return {"name": self.name,
"email": self.email}
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return str(self.id)
@app.route('/', methods=['GET'])
def query_records():
name = request.args.get('name')
user = User.objects(name=name).first()
if not user:
return jsonify({'error': 'data not found'})
else:
return jsonify(user.to_json())
@app.route('/', methods=['PUT'])
@login_required
def create_record():
record = json.loads(request.data)
user = User(name=record['name'],
password=record['password'],
email=record['email'])
user.save()
return jsonify(user.to_json())
@app.route('/', methods=['POST'])
@login_required
def update_record():
record = json.loads(request.data)
user = User.objects(name=record['name']).first()
if not user:
return jsonify({'error': 'data not found'})
else:
user.update(email=record['email'],
password=record['password'])
return jsonify(user.to_json())
@app.route('/', methods=['DELETE'])
@login_required
def delte_record():
record = json.loads(request.data)
user = User.objects(name=record['name']).first()
if not user:
return jsonify({'error': 'data not found'})
else:
user.delete()
return jsonify(user.to_json())
if __name__ == "__main__":
app.run(port=8080, debug=True)

Related course: Python Flask: Create Web Apps with Flask