Bagaimana cara Mengamankan Flask REST API dengan JSON Web Token?

Mari kita pelajari cara mengamankan API REST dengan token web JSON untuk mencegah pengguna dan aplikasi pihak ketiga menyalahgunakannya.


Kami akan membangun layanan basis data menggunakan SQLite dan memungkinkan pengguna untuk mengaksesnya melalui REST API menggunakan metode HTTP seperti POST dan PUT.

Selain itu, kita akan mengetahui mengapa token web JSON adalah cara yang cocok untuk melindungi API lainnya daripada intisari dan otentikasi dasar. Sebelum kita melanjutkan, mari kita pahami istilah token web JSON, REST API, dan kerangka kerja Flask.

Token Web JSON

Token web JSON, juga dikenal sebagai JWT, adalah cara aman mentransfer token acak antara dua pihak atau entitas. JSON biasanya terdiri dari tiga bagian sebagai berikut.

  • Muatan
  • Header
  • Tanda tangan

JSON menggunakan dua jenis formulir struktur saat mentransfer data atau informasi antara dua pihak.

  • Serialized
  • Deserialized

Bentuk serial digunakan ketika mentransfer data ke jaringan melalui setiap permintaan dan tanggapan sementara formulir deserialized digunakan ketika membaca dan menulis data ke token web.

Dalam bentuk serial, ada tiga komponen.

  • Header
  • Muatan
  • Tanda tangan

Komponen header mendefinisikan informasi kriptografi tentang token. Sebagai contoh:

  • Apakah JWT ditandatangani atau tidak ditandatangani?
  • Tentukan teknik algoritma

Bentuk deserialized, tidak seperti bentuk serial, mengandung dua komponen.

  • Muatan
  • Header

API SISA

API (antarmuka pemrograman aplikasi) memungkinkan komunikasi antara dua aplikasi untuk mengambil atau mengirimkan data. Ada dua jenis API yang populer – API web dan sistem.

Pada artikel ini, kita hanya akan melihat API web. Ada dua jenis API web.

  • Permintaan – API Respons: Istirahat, GraphQL, Panggilan Prosedur Jauh (RPC)
  • API Berbasis Acara: WebHooks, Soket Web, Streaming HTTP

REST API termasuk dalam kategori permintaan-respons. Itu menggunakan metode HTTP seperti GET, POST, dan PUT untuk melakukan operasi API.

Contoh klasik adalah ketika pengguna mengirim metode GET ke layanan web untuk meminta atau mengambil sumber daya tertentu atau kumpulan sumber daya. Server kemudian mengirimkan kembali sumber daya spesifik atau kumpulan sumber daya kembali ke pengguna yang memintanya.

Kerangka Flask

Labu adalah kerangka kerja yang didasarkan pada python. Ini adalah kerangka kerja mikro yang digunakan oleh pengembang python untuk membangun API lainnya. Ini disebut kerangka mikro karena memungkinkan pengembang, misalnya, untuk menambahkan otentikasi khusus dan sistem backend lainnya berdasarkan preferensi.

Mari kita mulai dengan implementasinya. Pengaturan sistem saya adalah sebagai berikut.

  • Ubuntu sebagai OS
  • Python 2.7+
  • Tukang pos

Siapkan lingkungan virtual menggunakan virtualenv

Kita perlu mengatur lingkungan virtual untuk memastikan bahwa beberapa paket tidak akan bertentangan dengan paket sistem. Mari kita gunakan virtualenv untuk menyiapkan lingkungan virtual baru.

Dengan anggapan Anda memiliki perintah pip yang tersedia di sistem Anda, jalankan perintah berikut melalui pip untuk menginstal.

pip instal virtualenv

Jika Anda tidak memiliki pip pada mesin Anda, maka ikuti ini dokumentasi untuk menginstal pip pada sistem Anda.

Selanjutnya, mari kita buat direktori untuk menyimpan atau menahan lingkungan virtual kita. Gunakan perintah mkdir yang ditunjukkan di bawah ini untuk membuat direktori

proyek mkdir flask

Ubah ke direktori proyek flask menggunakan perintah berikut

proyek cd flask

Di dalam direktori proyek flask, gunakan alat virtualenv untuk membuat lingkungan virtual seperti yang ditunjukkan di bawah ini:

virtualenv flaskapi

Setelah Anda menggunakan alat virtualenv untuk membuat lingkungan virtual, jalankan perintah cd untuk berubah ke direktori flaskapi sebagai lingkungan virtual dan aktifkan menggunakan perintah di bawah ini.

sumber bin / aktifkan

Jalankan semua tugas yang terkait dengan proyek ini dalam lingkungan virtual.

Instal paket menggunakan pip

Sekarang saatnya untuk menginstal paket seperti kerangka kerja lab dan PyJWT yang akan kita gunakan untuk membangun API sisanya dan paket lain yang diperlukan untuk proyek API kami.

Buat file requirement.txt dengan paket-paket berikut.

Labu
tanggal Waktu
uuid
Labu-SQLAlchemy
PyJWT

Instal dengan pip.

pip instal -r requirement.txt

Siapkan basis data

Mari kita instal SQLite.

apt-get install sqlite3

Buat database bernama perpustakaan. Di dalam database ini, kita akan membuat dua tabel, yaitu tabel Users dan Authors.

Tabel pengguna akan berisi pengguna terdaftar. Hanya pengguna terdaftar yang dapat memiliki akses ke tabel Penulis.

Tabel penulis akan menyimpan informasi atau detail penulis seperti nama penulis, negara tempat lahir dan sebagainya yang dikirimkan oleh pengguna terdaftar.

Buat database menggunakan perintah berikut:

sqlite3 library.db

Anda dapat memeriksa apakah Anda berhasil membuat database dengan menggunakan perintah di bawah ini:

.basis data

Buka terminal baru dan jalankan yang berikut di lingkungan virtual yang kami buat sebelumnya.

sentuh app.py

Rekatkan kode berikut di dalam file bernama app.py

dari flask import Flask, request, jsonify, make_response
dari flask_sqlalchemy, impor SQLAlchemy
dari werkzeug.security import generate_password_hash, check_password_hash
mengimpor uuid
impor jwt
impor datetime
dari functools import wraps

Baris pertama dalam kode di atas mengimpor paket seperti permintaan dan jsonify. Kami akan menggunakan permintaan untuk melacak data tingkat permintaan selama permintaan dan menggunakan jsonify untuk menghasilkan respons di a JSON format.

Pada baris berikutnya, kami mengimpor SQLAlchemy dari flask_sqlalchemy untuk mengintegrasikan fitur SQLAlchemy ke dalam flask.

Dari werkzeug.security, kami mengimpor generate_password_hash untuk menghasilkan hash kata sandi untuk pengguna dan check_password_hash untuk memeriksa kata sandi pengguna ketika membandingkan kata sandi yang dikirimkan oleh pengguna dengan kata sandi pengguna yang disimpan dalam database.

Akhirnya, kami mengimpor uuid yang juga dikenal sebagai pengidentifikasi unik universal untuk menghasilkan nomor id acak bagi pengguna.

Namun, di dalam file app.py, terapkan pengaturan konfigurasi untuk API pustaka menggunakan kode di bawah ini di dalam file app.py.

Tempatkan kode berikut di bawah pernyataan impor.

app = Labu (__ name__)

app.config [‘SECRET_KEY’] = ‘Th1s1ss3cr3t’
app.config [‘SQLALCHEMY_DATABASE_URI’] = ‘sqlite: /////home/michael/geekdemos/geekapp/library.db’
app.config [‘SQLALCHEMY_TRACK_MODIFICATIONS’] = Benar

db = SQLAlchemy (aplikasi)

Sekarang buat dua model untuk tabel Users dan Authors seperti yang ditunjukkan di bawah ini. Salin dan tempel kode di dalam file app.py.

Tempatkan kode di bawah ini tepat di bawah pengaturan basis data ini db = SQLAlchemy (app)

Pengguna kelas (db.Model):
id = db.Column (db.Integer, primary_key = True)
public_id = db.Column (db.Integer)
name = db.Column (db.String (50))
password = db.Column (db.String (50))
admin = db.Column (db.Boolean)
Penulis kelas (db.Model):
id = db.Column (db.Integer, primary_key = True)
name = db.Column (db.String (50), unique = True, nullable = False))
book = db.Column (db.String (20), unique = True, nullable = False))
negara = db.Column (db.String (50), nullable = False))
booker_prize = db.Column (db.Boolean)

Hasilkan Pengguna dan Tabel Penulis

Di terminal, ketikkan kode berikut di dalam lingkungan virtual untuk membuat atau membuat tabel untuk tabel Users dan Authors seperti yang ditunjukkan di bawah ini

dari aplikasi impor db
db.create_all ()

Setelah itu, buka file app.py di dalam lingkungan virtual dan buat fungsi lain.

Fungsi ini akan menghasilkan token untuk memungkinkan hanya pengguna terdaftar untuk mengakses dan melakukan serangkaian operasi API terhadap tabel Penulis.

Tempatkan kode ini di bawah model database untuk tabel Penulis

def token_required (f):
@wraps (f)
dekorator def (* args, ** kwargs):

token = Tidak Ada

jika ‘x-access-token’ di request.headers:
token = request.headers [‘x-access-token’]

jika tidak token:
return jsonify ({‘message’: ‘token yang valid tidak ada’})

mencoba:
data = jwt.decode (token, app.config [SECRET_KEY])
current_user = Users.query.filter_by (public_id = data [‘public_id’]). first ()
kecuali:
return jsonify ({‘message’: ‘token tidak valid’})

return f (current_user, * args, ** kwargs)
dekorator kembali

Buat rute untuk tabel pengguna

Sekarang mari kita buat rute untuk memungkinkan pengguna mendaftar untuk API Penulis melalui nama pengguna dan kata sandi seperti yang ditunjukkan di bawah ini.

Sekali lagi buka file app.py di dalam lingkungan virtual dan rekatkan kode berikut di bawah fungsi token_required (f)

@ app.route (‘/ register’, methods = [‘GET’, ‘POST’])
def signup_user ():
data = request.get_json ()

hashed_password = menghasilkan_password_hash (data [‘kata sandi’], metode = ‘sha256’)

new_user = Pengguna (public_id = str (uuid.uuid4 ()), name = data [‘name’], kata sandi = hashed_password, admin = Salah)
db.session.add (new_user)
db.session.commit ()

return jsonify ({‘message’: ‘berhasil terdaftar’})

Di dalam lingkungan virtual, buat rute lain di file app.py untuk memungkinkan pengguna terdaftar untuk masuk.

Ketika pengguna masuk, token acak dihasilkan bagi pengguna untuk mengakses API perpustakaan.

Rekatkan kode di bawah di bawah rute sebelumnya yang kami buat.

@ app.route (‘/ login’, methods = [‘GET’, ‘POST’])
def login_user ():

auth = request.authorization

jika tidak auth atau tidak auth.username atau tidak auth.password:
return make_response (‘tidak dapat memverifikasi’, 401, {‘WWW.Authentication’: ‘Realm dasar: "login dibutuhkan"’})

user = Users.query.filter_by (name = auth.username) .first ()

jika check_password_hash (user.password, auth.password):
token = jwt.encode ({‘public_id’: user.public_id, ‘exp’: datetime.datetime.utcnow () + datetime.timedelta (menit = 30)}, app.config [‘SECRET_KEY’])
return jsonify ({‘token’: token.decode (‘UTF-8’)})

return make_response (‘tidak dapat memverifikasi’, 401, {‘WWW.Authentication’: ‘Realm dasar: "login dibutuhkan"’})

Namun, dalam lingkungan virtual, buat rute lain di file app.py untuk mendapatkan atau mengambil semua pengguna terdaftar.

Kode ini memeriksa semua pengguna terdaftar di tabel Users dan mengembalikan hasil akhir dalam format JSON.

Rekatkan kode di bawah ini di bawah rute masuk

@ app.route (‘/ users’, methods = [‘GET’])
def get_all_users ():

users = Users.query.all ()

hasil = []

untuk pengguna di pengguna:
user_data = {}
user_data [‘public_id’] = user.public_id
user_data [‘name’] = user.name
user_data [‘password’] = user.password
user_data [‘admin’] = user.admin

result.append (user_data)

return jsonify ({‘users’: result})

Buat rute untuk tabel penulis 

Mari kita buat rute untuk tabel Penulis untuk memungkinkan pengguna untuk mengambil semua penulis dalam database, serta menghapus penulis.

Hanya pengguna dengan token yang valid yang dapat melakukan operasi API ini.

Di dalam file app.py, buat rute untuk pengguna terdaftar untuk membuat penulis baru.

Rekatkan kode ini di bawah rute yang memungkinkan pengguna untuk mengambil semua pengguna terdaftar.

@ app.route (‘/ author’, methods = [‘POST’, ‘GET’])
@token_required
def create_author (current_user):

data = request.get_json ()

new_authors = Penulis (nama = data [‘nama’], negara = data [‘negara’], buku = data [‘buku’], booker_prize = Benar, user_id = current_user.id)
db.session.add (new_authors)
db.session.commit ()

return jsonify ({‘message’: ‘penulis baru dibuat’})

Selanjutnya, buat rute lain untuk memungkinkan pengguna terdaftar dengan token yang valid untuk mengambil semua penulis di tabel Penulis seperti yang ditunjukkan di bawah ini.

Rekatkan kode ini di bawah rute yang memungkinkan pengguna membuat penulis baru.

@ app.route (‘/ penulis’, methods = [‘POST’, ‘GET’])
@token_required
def get_authors (current_user):

penulis = Authors.query.filter_by (user_id = current_user.id) .all ()

output = []
untuk penulis dalam penulis:

author_data = {}
author_data [‘name’] = author.name
author_data [‘book’] = author.book
author_data [‘country’] = author.country
author_data [‘booker_prize’] = author.booker_prize
output.append (author_data)

return jsonify ({‘list_of_authors’: output})

Akhirnya, masih di dalam file app.py, buat rute untuk menghapus penulis yang ditentukan seperti yang ditunjukkan di bawah ini.

Tempel kode ini di bawah rute yang memungkinkan pengguna untuk mengambil daftar penulis.

@ app.route (‘/ penulis /’, methods = [‘DELETE’])
@token_required
def delete_author (current_user, author_id):
author = Author.query.filter_by (id = author_id, user_id = current_user.id) .first ()
jika tidak penulis:
return jsonify ({‘message’: ‘author not exist’})

db.session.delete (penulis)
db.session.commit ()

return jsonify ({‘message’: ‘Author delete’})

if __name__ == ‘__main__’:
app.run (debug = True)

Setelah itu, simpan dan tutup file app.py di dalam lingkungan virtual.

Menguji API perpustakaan dengan tukang pos

Di bagian ini, kami akan menggunakan alat tukang pos untuk mengirim permintaan ke layanan basis data. Jika Anda tidak memiliki tukang pos di mesin Anda, Anda dapat mengetahui cara mengunduh dan memasangnya sini.

Selain tukang pos, kita dapat menggunakan alat lain seperti Ikal untuk mengirim permintaan ke server.

Buka terminal baru dan ketikkan yang berikut:

tukang pos

Tukang pos perintah akan menyebabkan peramban web Anda menampilkan halaman di bawah ini:

postman_signup

Anda dapat memutuskan untuk mendaftar dan membuat akun gratis tetapi kami akan melewati dan mendapatkan akses langsung ke aplikasi untuk menguji API perpustakaan seperti yang ditunjukkan di bawah ini:

Tes api perpustakaan

Di bagian ini, kami akan mengizinkan pengguna untuk mendaftar ke API perpustakaan dengan memberikan nama pengguna dan kata sandi unik dalam format JSON menggunakan metode POST menggunakan langkah-langkah berikut:

  • Klik pada tab berlabel Tubuh
  • Kemudian pilih tombol mentah dan pilih format JSON
  • masukkan nama pengguna dan kata sandi untuk mendaftar seperti yang ditunjukkan pada tangkapan layar
  • Di samping tombol kirim, masukkan URL berikut http://127.0.0.1/register
  • Akhirnya, ubah metode menjadi POST dan tekan tombol kirim.

seorang pengguna mendaftar untuk api

Ini akan menampilkan output berikut seperti yang ditunjukkan di bawah ini:

Sekarang kami telah berhasil mendaftarkan pengguna. Mari kita lanjutkan untuk mengizinkan pengguna yang baru saja mendaftar untuk masuk guna menghasilkan token acak sementara untuk mengakses tabel Penulis menggunakan langkah-langkah berikut:

  •  Klik pada tab otorisasi.
  • Di bawah bagian tipe, pilih otentikasi dasar.
  • Kemudian isi formulir nama pengguna dan kata sandi dengan nama pengguna dan kata sandi yang Anda daftarkan sebelumnya.
  • Terakhir, tekan tombol kirim untuk login dan buat token acak.

Setelah pengguna berhasil masuk, token acak dihasilkan untuk pengguna seperti yang ditunjukkan pada tangkapan layar.

Kami akan menggunakan token acak yang dihasilkan untuk mengakses tabel Penulis.

Di bagian ini, kami akan menambahkan informasi penulis ke tabel Penulis melalui metode POST menggunakan langkah-langkah berikut:

  • Klik pada tab tajuk
  • Sertakan tajuk HTTP berikut yang ditunjukkan pada tangkapan layar

  • Selanjutnya, klik pada tab tubuh dan masukkan detail penulis baru
  • Kemudian tekan tombol kirim untuk menambahkan detail penulis ke tabel Penulis

Anda juga dapat mengambil informasi penulis di tabel Penulis melalui yang berikut:

  • Pastikan token Anda yang dihasilkan ada di bagian tajuk. jika tidak ada di sana, Anda harus mengisinya dengan token Anda.
  • Di samping tombol kirim, masukkan URL ini http://127.0.0.1/authors
  • Kemudian ubah metode HTTP ke GET dan tekan tombol kirim untuk mengambil rincian penulis.

Akhirnya, Anda dapat menghapus penulis di tabel Penulis melalui metode DELETE menggunakan langkah-langkah berikut:

  • Pastikan token Anda masih di bagian tajuk. Anda dapat memeriksa tab header untuk memastikan informasi yang diperlukan tersedia.
  • Di samping tombol kirim, masukkan URL ini http://127.0.0.1/sam
  • Kemudian tekan tombol kirim untuk menghapus pengguna yang Anda tentukan.

Anda dapat menemukan kode sumber lengkap di Github.  Anda dapat mengkloningnya dan memeriksanya di mesin Anda.

TAGS:

  • Python

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map