گذرواژه‌ها، اطلاعات کارت اعتباری، شماره‌های شناسایی شخصی (PIN) – اینها همه دارایی‌های حیاتی هستند که برای مجوز و احراز هویت استفاده می‌شوند. این بدان معنی است که آنها باید از کاربران غیرمجاز محافظت شوند.

ما به عنوان توسعه‌دهندگان وظیفه داریم از این اطلاعات حساس محافظت کنیم و مهم است که اقدامات ایمن قوی را در برنامه‌های خود اجرا کنیم.

اکنون، مکانیسم‌های احراز هویت بسیاری مانند OAuth، OpenID Connect و JSON Web Tokens (JWT) برای ایمن کردن داده‌ها در دسترس هستند.

در این مقاله، روش استفاده از JWT ها را هنگام ایمن سازی اطلاعات در API با ادغام احراز هویت مبتنی بر JWT در یک برنامه Flask به شما نشان خواهم داد.

در اینجا چیزی است که این مقاله پوشش خواهد داد:

  • توکن وب JSON چیست؟
  • JWT ها چگونه کار می کنند؟
  • روش استفاده از توکن های وب JSON برای احراز هویت برنامه های Flask
    1. وابستگی ها را نصب کنید
    2. یک پایگاه داده و مدل کاربر ایجاد کنید
    3. برنامه را برای احراز هویت JWT پیکربندی کنید
    4. مسیرهای محافظت شده ایجاد کنید
    5. یک تابع ورود ایجاد کنید
  • نتیجه

پیش نیازها

برای دنبال کردن این آموزش به شما نیاز دارید:

  • آشنایی با روش های HTTP
  • درک روش ایجاد API در Flask
  • VS Code ویرایشگر (یا مشابه دیگر).
  • آ terminal

توکن وب JSON چیست؟

JSON Web Tokens یا JWTs یک مکانیسم احراز هویت هستند که برای انتقال امن اطلاعات بین یک کلاینت و یک سرور در قالب JSON استفاده می شود.

این اطلاعات را می توان تأیید و اعتماد کرد زیرا به صورت دیجیتالی با الگوریتم HMAC یا یک جفت کلید عمومی/خصوصی با استفاده از RSA یا ECDSA امضا شده است.

توکن ها به سه قسمت کدگذاری می شوند که هر کدام با یک نقطه تقسیم می شوند، مانند زیر:

Header.Payload.Signature
  • سرتیتر: این نوع توکن (JWT) و الگوریتم امضای مورد استفاده را مشخص می کند.
  • ظرفیت ترابری: این داده‌های خاص کاربر مانند شناسه کاربر، نام کاربری، نقش‌ها، و هرگونه ادعای دیگری را که می‌خواهید درج کنید، حمل می‌کند. این محموله برای حداکثر امنیت در Base64 کدگذاری شده است.
  • امضا: این یک ترکیب هش شده از هدر، بارگذاری و کلید مخفی سرور است. این یکپارچگی توکن را تضمین می کند و هر گونه تغییر در توکن شناسایی خواهد شد.

JWT ها چگونه کار می کنند؟

برای اینکه بفهمید JWT چگونه کار می کند، باید بدانید که توکن ها قرار است چه کاری انجام دهند. JWT ها برای مخفی کردن داده ها ایجاد نمی شوند، بلکه برای اطمینان از تأیید اعتبار داده های ارسال شده ایجاد می شوند. به همین دلیل است که JWT امضا و رمزگذاری شده است، نه رمزگذاری شده.

JWT به عنوان وسیله ای بدون حالت برای انتقال داده ها از مشتری به سرور عمل می کند. این بدان معنی است که هیچ شی جلسه ای را در مرورگر ذخیره نمی کند، بنابراین مرورگر وضعیت جلسه را بین درخواست ها حفظ نمی کند.

در عوض، JWT ها از نشانه ای استفاده می کنند که هر بار درخواستی در سرآیند درخواست ارسال می شود. این توکن تأیید می کند که توکن ارسال شده احراز هویت است و اجازه دسترسی به آن درخواست را دارد.

بیایید ببینیم چگونه این اتفاق می افتد:

  1. یک کاربر سعی می کند وارد شود و یک نام کاربری و رمز عبور ارسال می کند تا توسط سرور تأیید شود.
  2. تابع تأیید یک بررسی را انجام می دهد تا ببیند آیا مطابقت در پایگاه داده وجود دارد یا خیر.
  3. پس از اینکه کاربر با موفقیت احراز هویت شد (ورود به سیستم) با استفاده از اطلاعات خود (بارگذاری بار)، مانند شناسه کاربری یا نام کاربری، یک JWT توسط سرور تولید می‌شود و با استفاده از یک کلید مخفی آن را امضا می‌کند.
  4. JWT تولید شده به عنوان یک توکن حامل همراه با هر هدر درخواست ارسال می شود تا بررسی شود آیا کاربر برای انجام آن درخواست احراز هویت شده است یا خیر.
پیشنهاد می‌کنیم بخوانید:  چگونه یک سیستم کنترل موشک بسازیم: نظریه کنترل پایه با پایتون

روش استفاده از توکن های وب JSON برای احراز هویت برنامه های Flask

برای نشان دادن اینکه چگونه می توانید احراز هویت JWT را در Flask پیاده سازی کنید، یک برنامه کاربردی ساده ایجاد می کنیم که از JWT برای مدیریت عملکردهای ورود و دسترسی به مسیرهای محافظت شده استفاده می کند.

1. وابستگی ها را نصب کنید

این دستور را اجرا کنید تا وابستگی هایی که نیاز داریم را نصب کنیم

pip install flask flask-bcrypt Flask-JWT-Extended

بعد، مطمئن شوید import وابستگی ها و برنامه Flask خود را با این کد مقداردهی اولیه کنید:

from flask import Flask, jsonify, session, request, redirect, url_for
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity, get_jwt


app = Flask(__name__)

////WRITE MAIN CODE HERE


if __name__ == "__main__":
    with app.app_context():
        app.run(debug=True)

2. یک پایگاه داده و User Model ایجاد کنید

برای انجام این کار، از SQL-Alchemy استفاده می کنیم، که یک جعبه ابزار Python SQL است که استفاده از SQL را در اسکریپت های پایتون پیچیده تر می کند.

برای راه اندازی SQL Alchemy در برنامه خود، مراحل زیر را دنبال کنید:

ابتدا خود را باز کنید terminal یا خط فرمان را وارد کنید و دستور زیر را وارد کنید:

pip install sqlalchemy

این دستور SQLAlchemy را در محیط پایتون شما نصب می کند و آن را در فهرست پروژه شما در دسترس قرار می دهد.

در مرحله بعد، برنامه خود را طوری پیکربندی کنید که از سیستم مدیریت پایگاه داده (DBMS) ترجیحی شما استفاده کند. این آموزش از SQlite3 DBMS استفاده می کند زیرا به سرور جداگانه نیاز ندارد:

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'

این قطعه کد به Flask-SQLAlchemy دستور می دهد تا آن را ایجاد و استفاده کند site.db فایل را در دایرکتوری پروژه خود به عنوان پایگاه داده SQLite برای برنامه کاربردی.

سپس پایگاه داده را در برنامه خود مقداردهی کنید:

db = SQLAlchemy(app)

این نمونه از پایگاه داده به عنوان پلی بین برنامه و پایگاه داده عمل می کند.

اکنون User Model را ایجاد کنید که در این آموزش جزئیات کاربر را ذخیره می کنیم:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    password = db.Column(db.String(80), nullable=False)
    is_active = db.Column(db.Boolean(), default=True)
    cart = db.Column(JSON, nullable=True, default=list)  # Make cart nullable

    # Define the relationship between User and CartProducts
    cart_products = relationship('CartProducts', backref="user", lazy="dynamic")
    # Define the relationship between User and Wishlists
    wishlists = db.relationship('Wishlists', backref="user", lazy=True)

    def __repr__(self):
        return f'<User {self.username}>'

توجه داشته باشید: شما می توانید مدل های دیگری را با استفاده از همان نحو ایجاد کنید تا موجودیت های داده های مختلف را در برنامه خود نشان دهید.

3. برنامه را برای JWT Authentication پیکربندی کنید

برای پیاده سازی احراز هویت JWT در برنامه Flask خود، import کتابخانه های لازم و تنظیم تنظیمات مناسب با این کد:

from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, create_access_token, jwt_required

app = Flask(__name__)

# Configuration
app.config['SECRET_KEY'] = 'your_strong_secret_key'
app.config["JWT_SECRET_KEY"] = 'your_jwt_secret_key'
app.config['JWT_TOKEN_LOCATION'] = ['headers']

# Database Initialization
db = SQLAlchemy(app)

# JWT Initialization
jwt = JWTManager(app)

# Rest of the application code (routes, etc.)

این قطعه کد اجزای زیر را برای برنامه ما وارد می کند:

  • app.config[‘SECRET_KEY’] کلید مخفی برنامه Flask را تنظیم می کند که برای امضای ایمن کوکی های جلسه و سایر نیازهای مرتبط با امنیت استفاده می شود.
  • app.config[‘JWT_SECRET_KEY’] کلید مخفی مورد استفاده برای رمزگذاری و رمزگشایی JWT ها را برای عملیات Flask-JWT تنظیم می کند.
  • app.config[‘JWT_TOKEN_LOCATION’] مشخص می کند که برنامه باید کجا به دنبال JWT باشد. در اینجا تنظیم شده است که در هدرهای HTTP نگاه شود.
پیشنهاد می‌کنیم بخوانید:  چگونه با پایتون یک Job Board Scraper بسازیم

وقتی این را تنظیم کردیم، می‌توانیم نقاط پایانی و مسیرهایی را که قصد محافظت از آنها را داریم ایجاد کنیم.

4. مسیرهای محافظت شده ایجاد کنید

مسیرهای محافظت شده صفحاتی هستند که ما قصد داریم آنها را از دید کاربران غیرمجاز مخفی نگه داریم.

به عنوان مثال، بیایید فرض کنیم سعی می کنیم وارد مکانی شویم که مختص اعضای یک جامعه است. اما یک نگهبان محل برگزاری را از دست “کاربران غیرمجاز” مانند ما ایمن می کند. در این شرایط، ما کاربران برنامه هستیم، محل برگزاری، نشانی اینترنتی است که از آن محافظت می کنیم، و نگهبانی که از مکان محافظت می کند، یک @jwt_required دکوراتور

را @jwt_required دکوراتور برای محافظت از مسیرهای خاصی که نیاز به احراز هویت دارند استفاده می شود. این دکوراتور قبل از اجازه دسترسی به page:

@app.route('/get_name', methods=['GET'])
@jwt_required()
def get_name():
    # Extract the user ID from the JWT
    user_id = get_jwt_identity()
    user = User.query.filter_by(id=user_id).first()

    # Check if user exists
    if user:
        return jsonify({'message': 'User found', 'name': user.name})
    else:
        return jsonify({'message': 'User not found'}), 404

در این قطعه کد، تابعی ایجاد کردیم که نام کاربر را پس از احراز هویت برمی گرداند. اگر توکن مفقود، نامعتبر یا منقضی شده باشد، درخواست رد می شود و معمولاً سرور یک HTTP برمی گرداند. 401 وضعیت غیر مجاز

5. یک صفحه ورود ایجاد کنید

در این نقطه پایانی، ما تابعی ایجاد خواهیم کرد که اعتبار نام کاربری و رمز عبور را از درخواست مشتری (به عنوان مثال، داده‌های فرم) می‌پذیرد و اعتبارنامه‌های دریافت‌شده از کاربر را با داده‌های کاربر در پایگاه داده مقایسه می‌کند. اگر مطابقت وجود داشته باشد، یک نشانه دسترسی JWT حاوی اطلاعات کاربر ایجاد می شود.

@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data['username']
    password = data['password']
    print('Received data:', username , password)

    user = User.query.filter_by(username=username).first()

    if user and bcrypt.check_password_hash(user.password, password):
        access_token = create_access_token(identity=user.id)
        return jsonify({'message': 'Login Success', 'access_token': access_token})
    else:
        return jsonify({'message': 'Login Failed'}), 401

در این مثال، این تابع اعتبار کاربر را در برابر پایگاه داده با استفاده از bcrypt برای تأیید رمز عبور ایمن هنگام دریافت درخواست POST بررسی می کند. اگر اعتبارنامه ها معتبر باشند، سرور یک JWT برای کاربر ایجاد می کند و به آنها امکان دسترسی به مسیرهای محافظت شده را می دهد.

در اینجا نمونه ای از فرم React است که درخواست POST را به نقطه پایانی ورود ارسال می کند:

import React from "react";
import axios from "axios";
import { useState } from "react";
import Footer from "./Footer";
// import "./Login.css";

function Login() {
  const [password, setPassword] = useState("");
  const [username, setUsername] = useState("");

  const handleLogin = async (event) => {
    event.preventDefault();
    const data = {
      username: username,
      Password: password,
    };

    try {
      const response = await axios.post("http://localhost:5000/login", {
        username,
        password,
      });
      localStorage.setItem("access_token", response.data.access_token);
      // Redirect to protected route
      alert("Login successful");
    } catch (error) {
      console.error(error);
      // Display error message to user
    }
  };

  const handleUsernameChange = (event) => {
    setUsername(event.target.value);
  };

  const handlePasswordChange = (event) => {
    setPassword(event.target.value);
  };

  return (
    <div >
      
          <form method="post" >
              <input
                type="text"
                id=""
                placeholder="Username"
                name="username"
                required
                value={username}
                onChange={handleUsernameChange}
              />
              <input
                type="text"
                id=""
                placeholder="Your email"
              />
              <input
                type="password"
                required
                placeholder="Your Password"
                name="password"
                value={password}
                onChange={handlePasswordChange}
              />
          </form>
          <button type="submit" onClick={handleLogin}>
            Log In
          </button>
       
    </div>
  );

}

export default Login;

در این کامپوننت React، یک فرم ورود به سیستم ارائه کردیم که از Axios برای ارسال درخواست POST به نقطه پایانی ورود استفاده می‌کند. ورودی های نام کاربری و رمز عبور را با استفاده از React مدیریت می کند useState hook و این مقادیر را پس از ارسال فرم ارسال می کند.

اگر ورود موفقیت آمیز باشد، یک JWT را در حافظه محلی ذخیره می کند. این به برنامه سمت سرویس گیرنده اجازه می دهد تا هنگام ارسال درخواست های احراز هویت شده به سرور، توکن را به راحتی بازیابی کند.

jwtDemo-1

نتیجه

در این مقاله، روش ایمن سازی API ها با JSON Web Tokens در Flask را یاد گرفتیم. ما اصول اولیه JWT ها، روش کار آنها را پوشش دادیم و گام به گام ارائه کردیم process برای اجرای این روش احراز هویت این شامل همه چیز از نصب وابستگی های ضروری گرفته تا ایجاد مدل های کاربر و محافظت از مسیرها بود.

شما می توانید بر این پایه بنا کنید، مانند افزودن توکن های تازه، ادغام با ارائه دهندگان OAuth شخص ثالث، یا مدیریت مجوزهای کاربر پیچیده تر.