Falsk Framework Session and Flask-Session

Keywords: Python Session Redis network ascii

Catalog

Cookie and Session

Cookie:#Storage size is limited, stored on the client, there is a security risk

Cookies, meaning cookies, were proposed by the W3C organization as a mechanism first developed by the Netscape community.Cookies are now standard, with all major browsers like IE,
Cookie s are supported by Netscape, Firefox, Opera, and so on.Since HTTP is a stateless protocol, the server cannot know the identity of a client from a network connection alone.What shall I do?
Give the clients a pass, one for each person, and they must carry their own.This allows the server to confirm the identity of the customer from the pass.This is how cookies work.

Session:#to perfect cookies

Session is another mechanism for recording customer status, except that cookies are saved in client browsers and Sessions are saved on servers.When the client browser accesses the server,
The server records client information on the server in some form.This is Session.Client browsers only need to look up the status of the client from the session when they access it again.
session is essentially a key-value pair stored on the server side.

Session storage mechanism in Falsk

Delegate to client custody mechanism implementation process
 1. Turn on and set Session-session["user"] = 123
 2.session serialized string
 3. Encrypt with secret_key key key
 4. Return to client via Cookie

Receive Session
 1. Get session from client Cookie
 2. Decrypt by secret_key key key
 3. Deserialization Dictionary
 4. Get session

Advantages: No server resources
 Disadvantages: Relatively poor security when stored on the client side

#Usually, we use the session module provided by three-party components to solve the security problems of flask session s, such as Flask-Session, which can help us solve them.      

Related Configurations

Flask In Session
    - from flask import session
    - Use session The premise is that application Join in secret_key as:app.secret_key = "!@#$%^&*()"
    

#Session-related configurations must be reconfigured in code to take effect after a reboot
"SECRET_KEY": None,  # General Key
# Setup Method app.secret_key = "!@#$%^&*()"(Easy coding)  or  app.config['SECRET_KEY'] = "!@#$%^&*() "(High efficiency)

 session.pop('username')  #Delete username keys and values from session
 session.clear()          #Delete all session s

"SESSION_COOKIE_NAME": "session",
# Set session in Cookie Session name app.session_cookie_name ='session'

"SESSION_COOKIE_HTTPONLY": True,  
# Whether session should be opened only with HTTP requests
  
    
############################### Other Configurations ############################### 
    
{
    'DEBUG': False,               
    # Whether to turn on log-level low restart code error propagation for Debug mode development environment
    
    'TESTING': False,              
    # Whether to turn on test mode test environment log level is higher   
    
    'PROPAGATE_EXCEPTIONS': None,  
    # Exception propagation (whether LOG is printed in the console) is automatically True when Debug or testing is turned on
    
    'PRESERVE_CONTEXT_ON_EXCEPTION': None,  
    # One or two sentences are not clear, they are not usually used
    
    'SECRET_KEY': None,            
    # Turn on Session serialization, make sure you have it when you enable Session
    
    'PERMANENT_SESSION_LIFETIME': 31,  
    #  Session's life cycle (seconds) defaults to 31 seconds
    
    'USE_X_SENDFILE': False,  
    # Whether to discard x_sendfile
    
    'LOGGER_NAME': None,  
    # The name of the logger
    
    'LOGGER_HANDLER_POLICY': 'always',
    
    'SERVER_NAME': None,  # Service Access Domain Name
    
    'APPLICATION_ROOT': None,  # Full path to project
    
    'SESSION_COOKIE_NAME': 'session',  # Store session encrypted string name in cookies
    
    'SESSION_COOKIE_DOMAIN': None,  # Under which domain name session is generated and recorded in cookies
    
    'SESSION_COOKIE_PATH': None,  # Path to cookies
    
    'SESSION_COOKIE_HTTPONLY': True,  # Controls whether cookie s should be set to the httponly flag,
    
    'SESSION_COOKIE_SECURE': False,  # Controls whether cookie s should be set with security flags
    
    'SESSION_REFRESH_EACH_REQUEST': True,  # This flag controls how persistent sessions refresh
    
    'MAX_CONTENT_LENGTH': None,  
    # If set to the number of bytes, Flask rejects requests whose content length is longer than this value and returns a 413 status code
    
    'SEND_FILE_MAX_AGE_DEFAULT': 12,  # Maximum hours Default Cache Control Age
    
    'TRAP_BAD_REQUEST_ERRORS': False,
    # If this value is set to True, Flask will not perform error handling of HTTP exceptions, but will treat them like any other exception.
    # Bubble it out through the exception stack.This is useful in dire debugging scenarios where you need to find the source of HTTP exceptions.
    
    'TRAP_HTTP_EXCEPTIONS': False,
    # The internal data structure of Werkzeug handling specific data in the request throws a special key errors that are also exceptions to the "bad request".
    # Similarly, for consistency, many operations can explicitly throw BadRequest exceptions.
    # Because in debugging, you want to find out exactly why the exception occurred, this setting is used to debug in these situations.
    # If this value is set to True, you will only get a regular backtrace.
    
    'EXPLAIN_TEMPLATE_LOADING': False,
    
    'PREFERRED_URL_SCHEME': 'http',  # This value will be used when generating URLs if no URL mode is available
    
    'JSON_AS_ASCII': True,
    # Flask uses ascii encoding to serialize objects by default.If this value is set to False,
    # Flask does not encode it as ASCII and outputs it as is, returning its unicode string.
    # For example, jsonfiy automatically uses utf-8 to encode it before it is transmitted.
    
    'JSON_SORT_KEYS': True,
    #By default, Flask serializes JSON objects in the order of their keys.
    # This is done to ensure that the order of keys is not affected by the hash seed of the dictionary, so that the returned values are consistent each time and do not result in unnecessary additional HTTP caches.
    # You can override the default action by modifying the value of this configuration.However, this is not recommended because this default behavior can potentially improve your performance at the cost.
    
    'JSONIFY_PRETTYPRINT_REGULAR': True,
    'JSONIFY_MIMETYPE': 'application/json',
    'TEMPLATES_AUTO_RELOAD': None,
}    

Use the Flask-Session tripartite component

install

#flask_session is a plug-in for the flask framework to implement session functionality, which replaces the session implementation mechanism that comes with flask.

#install 
pip3 install flask-session 

#Flask-Session supports sessions to be saved in several places such as:
- redis     #Store on the intranet instead of on the public network
- memcached
- filesystem
- mongodb
- sqlalchmey

#Store in redis instance
import redis
from flask import Flask, session
from flask_session import Session
  
app = Flask(__name__)
app.debug = True
app.secret_key = 'xxxx'
  
app.config['SESSION_TYPE'] = 'redis' # session type is redis
app.config['SESSION_PERMANENT'] = False # If set to True, closing the browser session will fail.
app.config['SESSION_USE_SIGNER'] = False # Whether to encrypt cookie values sent to session s on browsers
app.config['SESSION_KEY_PREFIX'] = 'session:' # Prefix of values saved to session
app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port='6379', password='123123') # Configuration for connecting redis
  
Session(app)
  
@app.route('/index')
def index():
  session['k1'] = 'v1'
  return 'xx'
  
if __name__ == '__main__':
  app.run()

Flask-Session File Directory

################################  Code  ################################
# _u init_u.py Session configuration code
from flask import Flask,request,session
from flask_session import Session
from redis import Redis

from app01.views.user import user_bp

def create_app():
    app = Flask(__name__)

    app.config["DEBUG"] = True
    app.config["SESSION_TYPE"] = "redis" 
    app.config["SESSION_REDIS"] = Redis(host="127.0.0.1",port=6379,db=15)

    # app.session_interface = SecureCookieSessionInterface()  # Native Session
    
    # After Config
    
    # Space for Tripartite Components to Live
    Session(app)  #Complete replacement of flask_session with native Session

    # Before blueprints are imported
    app.register_blueprint(user_bp)
    
    return app


# app01.py blueprint code
from flask import Blueprint

# The blueprint is a Flask instance and cannot be run
user = Blueprint("user",__name__,url_prefix="/user") # Blueprint name can no longer be duplicated in the same Flask instance

@user.route("/reg")
def reg():
    return "user login was successful"

@user.route("/login")
def login():
    return "user Login Successful"

Basic exercises

demand

Use the following data to create a student details page
STUDENT_DICT = {
    1: {'name':'steel egg','age': 17,'gender':'unknown'},
    2: {'name':'iron egg','age': 19,'gender':'man'},
    3: {'name':'yam','age': 18,'gender':'female'},
}

Requirement:
1. Write the login page and successfully jump to the student profile page 
2. The student profile page shows only the student's ID name details. Click on the student details page to view it
 3. The student details page shows all the information IDs of this student
 4. Write login verification decorator based on Session Not logged in status can only access the login page after successful login can access the student profile page and the student details page

Reference Answer (python code)

from flask import Flask, request, render_template, redirect, session

STUDENT_DICT = {
    1: {'name': 'Steel Eggs', 'age': 17, 'gender': 'Unknown'},
    2: {'name': 'Iron Egg', 'age': 19, 'gender': 'male'},
    3: {'name': 'maidservant', 'age': 18, 'gender': 'female'},
}

app = Flask(__name__, template_folder='templates')#Instantiate a Flask class to specify where templates are stored
app.secret_key = "!@#$%^&*()"  # Key (encrypt session)
app.debug = True  # Open Debug Mode Modify Code Autorestart Project


def check(func):  # Decorator detects whether a user is logged in and uses the user value in session to make a judgment
    def inner(*args, **kwargs):
        if session.get('user') == 'gkf':
            ret = func(*args, **kwargs)
            return ret
        else:
            return redirect('/login')

    return inner


@app.route('/login', methods=['POST', 'GET'], endpoint='login')#Specify routes and receive requests, set endpoint
def login():
    if request.method == 'GET':
        return render_template('login.html')  #If a get request returns a login.html

    if request.method == 'POST':              #If it is a post request, take out the value entered on the page in request.form
        username = request.form.get('username').lower()
        password = request.form.get('password')
        if username == 'gkf' and password == '123':#If the account password is correct, set session["user"] = username
            session["user"] = username
            return redirect('/brief_introduction') #Redirect to brief_introduction
        else:
            return 'Account or password error'  #If the account password is incorrect, throw an error message

#Set endpoint='brief_introduction'so that it does not conflict with other view functions to use the decorator properly
@app.route('/brief_introduction', methods=('GET',), endpoint='brief_introduction')
@check  #Decorators must be added under @app.route(), or they will cause @app.route() to be unrecognized and error when used
def brief_introduction():
    return render_template('brief_introduction.html', st_obj=STUDENT_DICT)#Returns brief_introduction.html and passes in the STUDENT_DICT dictionary with the name st_obj


@app.route('/detailed', methods=('GET',), endpoint='detailed')
@check
def detailed():   #Remove the student number from the url returned from the front-end page and pass it to the template detailed.html for rendering
    s_id = request.args.get('id') #Validate the url carrying parameters to ensure the correct student number is returned
    if not s_id:
        return "Query error please try again"
    if not s_id.isdecimal():
        return "Query error please try again"
    s_id = int(s_id)
    num = STUDENT_DICT.get(s_id,'')
    if not num:
        return "Query error please try again"
    else:
        return render_template('detailed.html', id=s_id, st_obj=STUDENT_DICT)


if __name__ == '__main__':
    app.run()

Reference Answer (html code)

<!--templates lower login.html Code-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <title>Sign in</title>
</head>
<body>
<h1>User Login</h1>
<form action="" method="post" enctype="multipart/form-data">
  <p>User name: <input type="text" name="username"></p>
  <p>Password: <input type="password" name="password"></p>
  <input type="submit" value="Sign in">
</form>
</body>
</html>

<!--templates lower brief_introduction.html Code-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Introduction to Student Information</title>
</head>
<body>
<h1>Introduction to Student Information</h1>
<table border="1px">
    <thead>
    <tr>
        <th>number</th>
        <th>Full name</th>
        <th>operation</th>
    </tr>
    </thead>
    <tbody>
    {% for foo in st_obj %}
    <tr>
        <td>{{ foo }}</td>
        <td>{{ st_obj[foo].name }}</td>
        <!--Add student numbers to detailed Of url upper-->
        <td><a href="http://127.0.0.1:5000/detailed? Id={{foo}} ">Click to view details <a></td>
    </tr>
    {% endfor %}
    </tbody>
</table>
</body>
</html>

<!--templates lower detailed.html Code-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Student Details</title>
</head>
<body>
<h1>Student Details</h1>
<table border="1px">
    <thead>
    <tr>
        <th>number</th>
        <th>Full name</th>
        <th>Age</th>
        <th>Gender</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>{{ id }}</td>
        <td>{{ st_obj[id].name }}</td>
        <td>{{ st_obj[id].age }}</td>
        {% if st_obj[id].gender=='Unknown' %}<!--Judging Abnormal Gender,Modify display results-->
        <td>male</td>
        {% else %}
         <td>{{ st_obj[id].gender }}</td>
        {% endif %}
    </tr>
    </tbody>
</table>
</body>
</html>
Author: Guo Kaifeng
Source: https://www.cnblogs.com/guokaifeng/
Support blogger: If you feel the article is helpful to you, you can click on the bottom right corner of the article [Recommend ) One time.Your encouragement is the blogger's greatest motivation!
Self-explanatory: life, need to pursue; dream, need to insist; life, need to cherish; but on the way of life, more need to be strong.Start with gratitude, learn to love, love your parents, love yourself, love your friends, love others.

Posted by megaalf on Thu, 26 Sep 2019 20:08:32 -0700