Flask 中return为啥要make_response一下?

文章讲述了Flask开发中使用make_response()函数转换返回对象以增强响应控制的重要性,以及json.dumps()用于将Python对象转为JSON字符串便于客户端处理的必要性。
部署运行你感兴趣的模型镜像

<作为初学者的 · 我们只有细细的探索和了解下才能慢慢地培养我们编码的乐趣,提高我们code的兴趣>,同时我们心中的邪念也会摒弃掉,code在我们心中发芽。                                -张新政

我们为什么要用make_response()函数将字符串 字典 元组 对象等转换为一个响应对象?不转换会怎么样?为什么必须要转换?

        在Flask中,我们可以直接返回字符串、字典、元组等对象作为响应。但是,为了更好地控制响应的状态码、头部信息和内容类型等,我们通常会使用make_response()函数将这些对象转换为一个响应对象。

        如果不使用make_response()函数进行转换,那么Flask会默认将返回的对象视为一个字符串,并将其作为响应的内容返回。这样做的话,我们就无法对响应进行更细致的控制,例如设置状态码、添加头部信息、设置内容类型等。

        通过使用make_response()函数,我们可以将1 字符串、2 字典、3 元组、 4对象转换为一个响应对象,从而可以对响应进行更多的操作和设置。我们可以通过设置响应对象的属性来修改状态码、添加头部信息,还可以使用response.set_cookie()方法设置cookie等。

        因此,使用make_response()函数将字符串、字典、元组等转换为一个响应对象,可以让我们更加灵活地控制和定制响应的内容和属性

【works citation】 Copied from C知道

代码源码copied from 编程浪子的flask小程序点餐系统

    response = make_response(json.dumps({'code':200, 'msg':'登录成功~~'}))
    response.set_cookie( app.config['AUTH_COOKIE_NAME'], '%s#%s' % (
        UserService.geneAuthCode(user_info), user_info.uid), 60 * 60 * 24 * 120)   # 保存120填
    return response

json.dumps()函数的作用是将 Python对象 转换为 JSON格式的字符串。它可以将字典、列表等Python对象转换为JSON字符串,以便在 网络传输或存储时使用。

不用json.dumps 可以吗? 为什么非要用json.dumps?

        可以不使用json.dumps(),但是使用json.dumps()可以将 Python对象 转换为 JSON格式的字符串。在这个例子中,使用json.dumps()将字典对象转换为JSON字符串,然后将其作为响应的内容返回给客户端。这样做的好处是可以确保响应的内容是符合JSON格式的,方便客户端进行解析和处理。

        如果不使用json.dumps(),直接将字典对象 作为响应的内容返回,那么客户端在接收到响应后 可能 需要手动解析响应内容,这样会增加客户端的工作量,并且可能会出现解析错误的情况。 

        所以,使用json.dumps()可以确保响应内容的格式正确,并且方便客户端进行解析和处理。

set_cookie()函数用于 设置响应对象的cookie。它接受多个参数,其中包括cookie的名称、值、过期时间等。通过调用set_cookie()函数,可以将cookie添加到响应对象中,并在客户端保存。

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

import base64 import os import secrets import sys from datetime import datetime from functools import wraps import requests from cryptography.fernet import Fernet from flask import ( Flask, flash, g, jsonify, make_response, redirect, render_template, request, url_for, ) from flask_sqlalchemy import SQLAlchemy from sqlalchemy.exc import IntegrityError import hashlib db = SQLAlchemy() class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False) salt = db.Column(db.String(64), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) vault_entries = db.relationship('VaultEntry', backref='user', lazy=True, cascade='all, delete-orphan') class VaultEntry(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) label = db.Column(db.String(120), nullable=False) login = db.Column(db.String(120), nullable=False) password_encrypted = db.Column(db.Text, nullable=False) notes = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) def hash_password(password: str, salt: bytes) -> str: data = salt + password.encode('utf-8') for _ in range(50): data = hashlib.sha256(data).digest() return base64.b64encode(data).decode('utf-8') def verify_password(password: str, salt_b64: str, digest: str) -> bool: salt = base64.b64decode(salt_b64.encode('utf-8')) return hash_password(password, salt) == digest def generate_salt() -> bytes: return secrets.token_bytes(16) def create_app() -> Flask: app = Flask(__name__) app.config['SECRET_KEY'] = secrets.token_hex(32) app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///vault.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SIGN_SERVER'] = os.getenv('SIGN_SERVER', 'http://127.0.0.1:4444/sign') fernet_key = os.getenv('FERNET_KEY') if not fernet_key: raise RuntimeError('Missing FERNET_KEY environment variable. Generate one with `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"`.') app.config['FERNET_KEY'] = fernet_key db.init_app(app) fernet = Fernet(app.config['FERNET_KEY']) with app.app_context(): db.create_all() if not User.query.first(): salt = secrets.token_bytes(16) password = secrets.token_bytes(32).hex() password_hash = hash_password(password, salt) user = User( id=0, username='admin', password_hash=password_hash, salt=base64.b64encode(salt).decode('utf-8'), ) db.session.add(user) db.session.commit() flag = open('/flag').read().strip() flagEntry = VaultEntry( user_id=user.id, label='flag', login='flag', password_encrypted=fernet.encrypt(flag.encode('utf-8')).decode('utf-8'), notes='This is the flag entry.', ) db.session.add(flagEntry) db.session.commit() def login_required(view_func): @wraps(view_func) def wrapped(*args, **kwargs): uid = request.headers.get('X-User', '0') print(uid) if uid == 'anonymous': flash('Please sign in first.', 'warning') return redirect(url_for('login')) try: uid_int = int(uid) except (TypeError, ValueError): flash('Invalid session. Please sign in again.', 'warning') return redirect(url_for('login')) user = User.query.filter_by(id=uid_int).first() if not user: flash('User not found. Please sign in again.', 'warning') return redirect(url_for('login')) g.current_user = user return view_func(*args, **kwargs) return wrapped @app.route('/') def index(): uid = request.headers.get('X-User', '0') if not uid or uid == 'anonymous': return redirect(url_for('login')) return redirect(url_for('dashboard')) @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username', '').strip() password = request.form.get('password', '') confirm_password = request.form.get('confirm_password', '') if not username or not password: flash('Username and password are required.', 'danger') return render_template('register.html') if password != confirm_password: flash('Passwords do not match.', 'danger') return render_template('register.html') salt = generate_salt() password_hash = hash_password(password, salt) user = User( username=username, password_hash=password_hash, salt=base64.b64encode(salt).decode('utf-8'), ) db.session.add(user) try: db.session.commit() except IntegrityError: db.session.rollback() flash('Username already exists. Please choose another.', 'warning') return render_template('register.html') flash('Registration successful. Please sign in.', 'success') return redirect(url_for('login')) return render_template('register.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username', '').strip() password = request.form.get('password', '') user = User.query.filter_by(username=username).first() if not user or not verify_password(password, user.salt, user.password_hash): flash('Invalid username or password.', 'danger') return render_template('login.html') r = requests.get(app.config['SIGN_SERVER'], params={'uid': user.id}, timeout=5) if r.status_code != 200: flash('Unable to reach the authentication server. Please try again later.', 'danger') return render_template('login.html') token = r.text.strip() response = make_response(redirect(url_for('dashboard'))) response.set_cookie( 'token', token, httponly=True, secure=app.config.get('SESSION_COOKIE_SECURE', False), samesite='Lax', max_age=12 * 3600, ) return response return render_template('login.html') @app.route('/logout') def logout(): response = make_response(redirect(url_for('login'))) response.delete_cookie('token') flash('Signed out.', 'info') return response @app.route('/dashboard') @login_required def dashboard(): user = g.current_user entries = [ { 'id': entry.id, 'label': entry.label, 'login': entry.login, 'password': fernet.decrypt(entry.password_encrypted.encode('utf-8')).decode('utf-8'), 'notes': entry.notes, 'created_at': entry.created_at, } for entry in user.vault_entries ] return render_template('dashboard.html', username=user.username, entries=entries) @app.route('/passwords/new', methods=['POST']) @login_required def create_password(): user = g.current_user label = request.form.get('label', '').strip() login_value = request.form.get('login', '').strip() password_plain = request.form.get('password', '').strip() notes = request.form.get('notes', '').strip() or None if not label or not login_value or not password_plain: flash('Service name, login, and password are required.', 'danger') return redirect(url_for('dashboard')) encrypted_password = fernet.encrypt(password_plain.encode('utf-8')).decode('utf-8') entry = VaultEntry( user_id=user.id, label=label, login=login_value, password_encrypted=encrypted_password, notes=notes, ) db.session.add(entry) db.session.commit() flash('Password entry saved.', 'success') return redirect(url_for('dashboard')) @app.route('/passwords/<int:entry_id>', methods=['DELETE']) @login_required def delete_password(entry_id: int): user = g.current_user entry = VaultEntry.query.filter_by(id=entry_id, user_id=user.id).first() if not entry: return jsonify({'success': False, 'message': 'Entry not found'}), 404 db.session.delete(entry) db.session.commit() return jsonify({'success': True}) return app if __name__ == '__main__': flask_app = create_app() flask_app.run(host='127.0.0.1', port=5000, debug=False) 解析 package main import ( "crypto/rand" "encoding/hex" "fmt" "log" "net/http" "net/http/httputil" "strings" "time" "github.com/golang-jwt/jwt/v5" "github.com/gorilla/mux" ) var ( SecretKey = hex.EncodeToString(RandomBytes(32)) ) type AuthClaims struct { jwt.RegisteredClaims UID string `json:"uid"` } func RandomBytes(length int) []byte { b := make([]byte, length) if _, err := rand.Read(b); err != nil { return nil } return b } func SignToken(uid string) (string, error) { t := jwt.NewWithClaims(jwt.SigningMethodHS256, AuthClaims{ UID: uid, RegisteredClaims: jwt.RegisteredClaims{ Issuer: "Authorizer", Subject: uid, ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()), }, }) tokenString, err := t.SignedString([]byte(SecretKey)) if err != nil { return "", err } return tokenString, nil } func GetUIDFromRequest(r *http.Request) string { authHeader := r.Header.Get("Authorization") if authHeader == "" { cookie, err := r.Cookie("token") if err == nil { authHeader = "Bearer " + cookie.Value } else { return "" } } if len(authHeader) <= 7 || !strings.HasPrefix(authHeader, "Bearer ") { return "" } tokenString := strings.TrimSpace(authHeader[7:]) if tokenString == "" { return "" } token, err := jwt.ParseWithClaims(tokenString, &AuthClaims{}, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return []byte(SecretKey), nil }) if err != nil { log.Printf("failed to parse token: %v", err) return "" } claims, ok := token.Claims.(*AuthClaims) if !ok || !token.Valid { log.Printf("invalid token claims") return "" } return claims.UID } func main() { authorizer := &httputil.ReverseProxy{Director: func(req *http.Request) { req.URL.Scheme = "http" req.URL.Host = "127.0.0.1:5000" uid := GetUIDFromRequest(req) log.Printf("Request UID: %s, URL: %s", uid, req.URL.String()) req.Header.Del("Authorization") req.Header.Del("X-User") req.Header.Del("X-Forwarded-For") req.Header.Del("Cookie") if uid == "" { req.Header.Set("X-User", "anonymous") } else { req.Header.Set("X-User", uid) } }} signRouter := mux.NewRouter() signRouter.HandleFunc("/sign", func(w http.ResponseWriter, r *http.Request) { if !strings.HasPrefix(r.RemoteAddr, "127.0.0.1:") { http.Error(w, "Forbidden", http.StatusForbidden) } uid := r.URL.Query().Get("uid") token, err := SignToken(uid) if err != nil { log.Printf("Failed to sign token: %v", err) http.Error(w, "Failed to generate token", http.StatusInternalServerError) return } w.Write([]byte(token)) }).Methods("GET") log.Println("Sign service is running at 127.0.0.1:4444") go func() { if err := http.ListenAndServe("127.0.0.1:4444", signRouter); err != nil { log.Fatal(err) } }() log.Println("Authorizer middleware service is running at :5555") if err := http.ListenAndServe(":5555", authorizer); err != nil { log.Fatal(err) } } 找出flag
最新发布
10-20
C:\Users\ASUS\.conda\envs\wys\python.exe C:\Users\ASUS\Desktop\Pro\API\app.py Traceback (most recent call last): File "C:\Users\ASUS\Desktop\Pro\API\app.py", line 188, in <module> if not os.path.exists(app.config['UPLOAD_FOLDER']): KeyError: 'UPLOAD_FOLDER'from flask import Flask, request, jsonify, send_from_directory, make_response from flask_sqlalchemy import SQLAlchemy from flask_cors import CORS from functools import wraps # 新增 import os import uuid from datetime import datetime # 初始化Flask应用 app = Flask(__name__) # ================ CORS全局配置 ================ CORS(app, resources={ r"/*": { "origins": "http://localhost:5173", "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], "allow_headers": ["Content-Type", "Authorization", "X-Requested-With"], "supports_credentials": True, "expose_headers": ["Set-Cookie"] # 修改 } }) # ================ 新增认证中间件 ================ def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): # 从cookie获取用户ID user_id = request.cookies.get('user_id') if not user_id: return jsonify({"message": "未认证"}), 401 # 验证用户是否存在 user = User.query.get(user_id) if not user: return jsonify({"message": "用户不存在"}), 401 return f(*args, **kwargs) return decorated_function # ================ 修改登录接口 ================ @app.route('/login', methods=['POST', 'OPTIONS']) def login(): try: if request.method == 'OPTIONS': return _build_cors_preflight_response() data = request.get_json() username = data.get('username', '').strip() password = data.get('password', '') user = User.query.filter_by(username=username).first() if not user or user.password != password: return jsonify({"message": "认证失败"}), 401 # 创建响应并设置cookie response = jsonify({ "message": "登录成功", "user_id": user.id, "profile_completed": user.profile_completed, "avatar_url": f"/uploads/{user.avatar}" }) # 设置HTTP-only Cookie response.set_cookie( key='user_id', value=str(user.id), httponly=True, samesite='Lax', max_age=86400, # 1天有效期 secure=False, # 开发环境关闭 domain='localhost' ) return response, 200 except Exception as e: return jsonify({"message": f"服务器错误: {str(e)}"}), 500 # ================ 修改用户资料接口 ================ @app.route('/user/<int:user_id>', methods=['GET', 'PUT', 'OPTIONS']) @login_required # 新增认证装饰器 def user_profile(user_id): try: if request.method == 'OPTIONS': return _build_cors_preflight_response() # 从cookie获取当前用户 current_user_id = int(request.cookies.get('user_id')) # 验证用户权限 if current_user_id != user_id: return jsonify({"message": "无权访问"}), 403 user = User.query.get_or_404(user_id) if request.method == 'GET': return jsonify({ "username": user.username, "shop_name": user.shop_name, "phone": user.phone, "email": user.email }), 200 if request.method == 'PUT': data = request.get_json() if not data: return jsonify({"message": "请求体不能为空"}), 400 update_fields = { 'shop_name': data.get('shop_name'), 'phone': data.get('phone'), 'email': data.get('email') } for field, value in update_fields.items(): if value is not None and getattr(user, field) != value: setattr(user, field, value) db.session.commit() return jsonify({"message": "更新成功"}), 200 except Exception as e: db.session.rollback() app.logger.error(f"用户资料操作失败: {str(e)}") return jsonify({"message": "服务器错误"}), 500 # ================ 修改密码接口 ================ @app.route('/user/<int:user_id>/password', methods=['PUT', 'OPTIONS']) @login_required # 新增认证装饰器 def update_password(user_id): try: # 权限验证 current_user_id = int(request.cookies.get('user_id')) if current_user_id != user_id: return jsonify({"message": "无权操作"}), 403 user = User.query.get_or_404(user_id) data = request.get_json() if 'old_password' not in data or 'new_password' not in data: return jsonify({"message": "需要提供原密码和新密码"}), 400 if user.password != data['old_password']: return jsonify({"message": "原密码错误"}), 401 if len(data['new_password']) < 6: return jsonify({"message": "密码至少6位"}), 400 user.password = data['new_password'] user.password_updated_at = datetime.utcnow() db.session.commit() return jsonify({"message": "密码更新成功"}), 200 except Exception as e: db.session.rollback() return jsonify({"message": f"服务器错误: {str(e)}"}), 500 # ================ 工具函数 ================ def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in {'png', 'jpg', 'jpeg'} def _build_cors_preflight_response(): response = make_response() response.headers.add("Access-Control-Allow-Origin", "http://localhost:5173") response.headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With") response.headers.add("Access-Control-Allow-Methods", "*") response.headers.add("Access-Control-Max-Age", "86400") response.headers.add("Access-Control-Allow-Credentials", "true") response.headers['Access-Control-Allow-Origin'] = 'http://localhost:5173' response.headers['Access-Control-Allow-Credentials'] = 'true' response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization' return response, 204 # ================ 启动应用 ================ if __name__ == '__main__': # 确保上传目录存在 if not os.path.exists(app.config['UPLOAD_FOLDER']): os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) # 检查数据库连接 try: with app.app_context(): db.create_all() db.engine.connect() print("✅ 数据库连接成功") except Exception as e: print(f"❌ 数据库连接失败: {str(e)}") exit(1) app.run(host='0.0.0.0', port=5000, debug=True)
05-27
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xinzheng新政

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值