One place for hosting & domains

      Menambah

      Cara Menambah Autentikasi pada Aplikasi Anda dengan Flask-Login


      Pengantar

      Mengizinkan pengguna untuk log masuk ke aplikasi Anda adalah salah satu fitur paling umum yang akan ditambahkan ke aplikasi web Anda. Artikel ini akan membahas cara menambah autentikasi ke aplikasi Flask Anda dengan paket Flask-Login.

      Gif animasi dari aplikasi Flask dan kotak log masuk

      Kita akan membangun beberapa laman pendaftaran dan log masuk yang memungkinkan pengguna untuk log masuk dan mengakses laman-laman yang terlindungi, sedangkan pengguna yang tidak log masuk tidak dapat melihatnya. Kita akan mengambil informasi dari model pengguna dan menampilkannya di laman terlindungi kita ketika pengguna log masuk untuk menyimulasikan tampilan profil.

      Kita akan membahas yang berikut dalam artikel ini:

      • Menggunakan pustaka Flask-Login untuk manajemen sesi
      • Menggunakan utilitas Flash bawaan untuk melakukan hash kata sandi
      • Menambah laman terlindungi di aplikasi kita hanya untuk pengguna yang log masuk
      • Menggunakan Flask-SQLAlchemy untuk menciptakan model pengguna
      • Menciptakan formulir pendaftaran dan log masuk bagi pengguna kita untuk menciptakan akun dan log masuk
      • Memberikan pesan kesalahan flash ke pengguna ketika ada yang salah
      • Menggunakan informasi dari akun pengguna untuk menampilkan laman profil

      Kode sumber untuk proyek ini tersedia di GitHub.

      Prasyarat

      Untuk mengikuti tutorial ini, Anda membutuhkan hal berikut ini:

      Aplikasi kita akan menggunakan setelan pabrik aplikasi Flask dengan cetak biru. Kita akan memiliki satu cetak biru yang menangani segala sesuatu yang terkait dengan auth, dan kita akan memiliki cetak biru lainnya untuk rute reguler kita, yang termasuk indeks dan laman profil terlindungi. Dalam aplikasi sungguhan, Anda dapat mengurai fungsionalitas dengan cara apa pun yang Anda suka, tetapi solusi yang dibahas di sini akan bekerja dengan baik untuk tutorial ini.

      Berikut adalah diagram untuk memberikan gambaran tentang struktur berkas proyek Anda akan terlihat seperti apa setelah Anda menyelesaikan tutorial:

      .
      └── flask_auth_app
          └── project
              ├── __init__.py       # setup our app
              ├── auth.py           # the auth routes for our app
              ├── db.sqlite         # our database
              ├── main.py           # the non-auth routes for our app
              ├── models.py         # our user model
              └── templates
                  ├── base.html     # contains common layout and links
                  ├── index.html    # show the home page
                  ├── login.html    # show the login form
                  ├── profile.html  # show the profile page
                  └── signup.html   # show the signup form
      

      Seiring kita menjalani tutorial ini, kita akan menciptakan direktori dan berkas ini.

      Langkah 1 — Menginstal Paket

      Ada tiga paket utama yang diperlukan untuk proyek kita:

      • Flask
      • Flask-Login: untuk menangani sesi pengguna setelah autentikasi
      • Flask-SQLAlchemy: untuk mewakili antarmuka dan model pengguna dengan basis data kita

      Kita akan menggunakan SQLite untuk menghindari keharusan menginstal dependensi tambahan bagi basis data.

      Pertama-tama, kita akan mulai dengan menciptakan direktori proyek:

      Selanjutnya, kita perlu bernavigasi ke direktori proyek:

      Anda akan ingin menciptakan lingkungan Python jika Anda tidak memilikinya. Tergantung bagaimana Python terinstal pada mesin Anda, perintah Anda akan terlihat mirip seperti ini:

      • python3 -m venv auth
      • source auth/bin/activate

      Catatan: Anda dapat melihat tutorial yang relevan dengan lingkungan lokal untuk menyiapkan venv.

      Jalankan perintah berikut dari lingkungan virtual Anda untuk menginstal paket yang diperlukan:

      • pip install flask flask-sqlalchemy flask-login

      Karena kini Anda telah menginstal paket, Anda siap untuk menciptakan berkas aplikasi utama.

      Langkah 2 — Menciptakan Berkas Aplikasi Utama

      Mari kita mulai dengan menciptakan direktori project:

      Berkas pertama yang akan kita kerjakan adalah berkas __init__.py untuk proyek kita:

      Berkas ini akan memiliki fungsi untuk menciptakan aplikasi kita, yang akan menginisialisasi basis data dan mendaftarkan cetak biru kita. Saat ini, berkas ini tidak terlalu berguna, tetapi akan diperlukan selanjutnya untuk aplikasi kita. Kita perlu menginisialisasi SQLAlchemy, menetapkan beberapa nilai konfigurasi, dan mendaftarkan cetak biru kita di sini.

      project/__init__.py

      from flask import Flask
      from flask_sqlalchemy import SQLAlchemy
      
      # init SQLAlchemy so we can use it later in our models
      db = SQLAlchemy()
      
      def create_app():
          app = Flask(__name__)
      
          app.config['SECRET_KEY'] = 'secret-key-goes-here'
          app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
      
          db.init_app(app)
      
          # blueprint for auth routes in our app
          from .auth import auth as auth_blueprint
          app.register_blueprint(auth_blueprint)
      
          # blueprint for non-auth parts of app
          from .main import main as main_blueprint
          app.register_blueprint(main_blueprint)
      
          return app
      

      Setelah memiliki berkas aplikasi utama, kita dapat mulai menambahkan ke dalam rute kita.

      Langkah 3 — Menambahkan Rute

      Untuk rute, kita akan menggunakan dua cetak biru. Untuk cetak biru utama, kita akan memiliki laman beranda (/) dan laman profil (/profile) untuk setelah kita log masuk. Jika pengguna mencoba mengakses laman profil tanpa log masuk, mereka akan dikirim ke rute log masuk.

      Untuk cetak biru auth, kita akan memiliki rute untuk mengambil baik laman log masuk (/login) dan laman pendaftaran (/sign-up). Kita juga akan memiliki rute untuk menangani permintaan POST dari kedua rute itu. Terakhir, kita akan memiliki rute log keluar (/logout) untuk mengeluarkan pengguna aktif.

      Untuk sementara ini, kita akan mendefinisikan login, signup, dan logout dengan respons sederhana. Kita akan meninjaunya kembali pada langkah selanjutnya dan memperbaruinya dengan fungsionalitas yang diinginkan.

      Pertama-tama, ciptakan main.py untuk main_blueprint:

      project/main.py

      from flask import Blueprint
      from . import db
      
      main = Blueprint('main', __name__)
      
      @main.route('/')
      def index():
          return 'Index'
      
      @main.route('/profile')
      def profile():
          return 'Profile'
      

      Selanjutnya, ciptakan auth.py untuk auth_blueprint:

      project/auth.py

      from flask import Blueprint
      from . import db
      
      auth = Blueprint('auth', __name__)
      
      @auth.route('/login')
      def login():
          return 'Login'
      
      @auth.route('/signup')
      def signup():
          return 'Signup'
      
      @auth.route('/logout')
      def logout():
          return 'Logout'
      

      Di dalam terminal, Anda dapat menetapkan nilai FLASK_APP dan FLASK_DEBUG:

      • export FLASK_APP=project
      • export FLASK_DEBUG=1

      Variabel lingkungan FLASK_APP memberi instruksi pada Flask terkait cara memuat aplikasi. Ini harus mengarah ke tempat create_app berada. Untuk keperluan kita, kita akan mengarahkan ke direktori project.

      Variabel lingkungan FLASK_DEBUG diaktifkan dengan menetapkan nilainya menjadi 1. Ini akan mengaktifkan pengawakutu yang akan menampilkan kesalahan aplikasi di peramban.

      Pastikan Anda berada di direktori flask_auth_app, lalu jalankan proyeknya:

      Sekarang, dalam peramban web, Anda seharusnya dapat bernavigasi ke lima URL yang memungkinkan dan melihat teks yang dihasilkan yang didefinisikan dalam auth.py dan main.py.

      Misalnya, mengunjungi localhost:5000/profile akan menampilkan: Profile:

      Tangkapan layar dari proyek di localhost porta 5000 dalam peramban

      Kini setelah kita memverifikasi bahwa rute berperilaku seperti yang diharapkan, kita dapat melanjutkan ke penciptaan templat.

      Langkah 4 — Menciptakan Templat

      Mari kita lanjutkan dan menciptakan templat yang digunakan dalam aplikasi. Ini adalah langkah pertama sebelum kita dapat menerapkan fungsionalitas log masuk yang sebenarnya. Aplikasi kita akan menggunakan empat templat:

      • index.html
      • profile.html
      • login.html
      • signup.html

      Kita juga akan memiliki templat dasar yang akan memiliki kode umum untuk setiap lamannya. Dalam hal ini, templat dasar akan memiliki tautan navigasi dan tata letak umum dari laman. Mari kita ciptakan sekarang.

      Pertama-tama, ciptakan direktori template di bawah direktori project:

      • mkdir -p project/templates

      Kemudian, ciptakan base.html:

      • nano project/templates/base.html

      Selanjutnya, tambahkan kode berikut ke berkas base.html:

      project/templates/base.html

      <!DOCTYPE html>
      <html>
      
      <head>
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <title>Flask Auth Example</title>
          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
      </head>
      
      <body>
          <section class="hero is-primary is-fullheight">
      
              <div class="hero-head">
                  <nav class="navbar">
                      <div class="container">
      
                          <div id="navbarMenuHeroA" class="navbar-menu">
                              <div class="navbar-end">
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.index') }}" class="navbar-item">
                                      Home
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.profile') }}" class="navbar-item">
                                      Profile
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.login') }}" class="navbar-item">
                                      Login
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.signup') }}" class="navbar-item">
                                      Sign Up
                                  </a>
                                  <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.logout') }}" class="navbar-item">
                                      Logout
                                  </a>
                              </div>
                          </div>
                      </div>
                  </nav>
              </div>
      
              <div class="hero-body">
                  <div class="container has-text-centered">
                     {% block content %}
                     {% endblock %}
                  </div>
              </div>
          </section>
      </body>
      
      </html>
      

      Kode ini akan menciptakan serangkaian menu yang terhubung ke setiap laman dari aplikasi dan daerah tempat konten akan muncul.

      Catatan: Di balik layar, kita menggunakan Bulma untuk menangani pengaturan gaya dan tata letak. Untuk pengetahuan yang lebih dalam tentang Bulma, pertimbangkan untuk membaca dokumentasi Bulma resmi.

      Selanjutnya, ciptakan templates/index.html:

      • nano project/templates/index.html

      Tambahkan kode berikut ke berkas yang baru saja diciptakan untuk menambahkan konten ke laman:

      project/templates/index.html

      {% extends "base.html" %}
      
      {% block content %}
      <h1 class="title">
        Flask Login Example
      </h1>
      <h2 class="subtitle">
        Easy authentication and authorization in Flask.
      </h2>
      {% endblock %}
      

      Kode ini akan menciptakan laman indeks dasar dengan judul dan subjudul.

      Selanjutnya, ciptakan templates/login.html:

      • nano project/templates/login.html

      Kode ini menghasilkan laman log masuk dengan bidang untuk Surel dan Kata Sandi. Ada juga kotak centang untuk “mengingat” suatu sesi log masuk.

      project/templates/login.html

      {% extends "base.html" %}
      
      {% block content %}
      <div class="column is-4 is-offset-4">
          <h3 class="title">Login</h3>
          <div class="box">
              <form method="POST" action="/login">
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus="">
                      </div>
                  </div>
      
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="password" name="password" placeholder="Your Password">
                      </div>
                  </div>
                  <div class="field">
                      <label class="checkbox">
                          <input type="checkbox">
                          Remember me
                      </label>
                  </div>
                  <button class="button is-block is-info is-large is-fullwidth">Login</button>
              </form>
          </div>
      </div>
      {% endblock %}
      

      Selanjutnya, ciptakan templates/signup.html:

      • nano project/templates/signup.html

      Tambahkan kode berikut untuk menciptakan laman pendaftaran dengan bidang untuk surel, nama, dan kata sandi:

      project/templates/signup.html

      {% extends "base.html" %}
      
      {% block content %}
      <div class="column is-4 is-offset-4">
          <h3 class="title">Sign Up</h3>
          <div class="box">
              <form method="POST" action="/signup">
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="email" name="email" placeholder="Email" autofocus="">
                      </div>
                  </div>
      
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="text" name="name" placeholder="Name" autofocus="">
                      </div>
                  </div>
      
                  <div class="field">
                      <div class="control">
                          <input class="input is-large" type="password" name="password" placeholder="Password">
                      </div>
                  </div>
      
                  <button class="button is-block is-info is-large is-fullwidth">Sign Up</button>
              </form>
          </div>
      </div>
      {% endblock %}
      

      Selanjutnya, ciptakan templates/profile.html:

      • nano project/templates/profile.html

      Tambahkan kode ini untuk menciptakan laman sederhana dengan judul yang dikodekan secara permanen untuk menyambut Anthony:

      project/templates/profile.html

      {% extends "base.html" %}
      
      {% block content %}
      <h1 class="title">
        Welcome, Anthony!
      </h1>
      {% endblock %}
      

      Nanti, kita akan menambahkan kode untuk menyapa pengguna siapa pun secara dinamis.

      Setelah Anda menambah templat, kita dapat memperbarui pernyataan respons di setiap rute ketika kita harus memberikan templat alih-alih teks.

      Selanjutnya, perbarui main.py dengan memodifikasi baris impor dan rute untuk index dan profile:

      project/main.py

      from flask import Blueprint, render_template
      ...
      @main.route('/')
      def index():
          return render_template('index.html')
      
      @main.route('/profile')
      def profile():
          return render_template('profile.html')
      

      Sekarang Anda akan memperbarui auth.py dengan memodifikasi baris impor dan rute untuk login dan signup:

      project/auth.py

      from flask import Blueprint, render_template
      ...
      @auth.route('/login')
      def login():
          return render_template('login.html')
      
      @auth.route('/signup')
      def signup():
          return render_template('signup.html')
      

      Setelah Anda membuat perubahan ini, laman pendaftaran akan terlihat seperti ini jika Anda bernavigasi ke /sign-up:

      Laman pendaftaran di /signup

      Anda seharusnya dapat melihat laman untuk /, /login, dan /profile juga.

      Kita akan membiarkan /logout untuk saat ini karena /logout tidak akan menampilkan templat saat selesai.

      Langkah 5 — Menciptakan Model Pengguna

      Model pengguna kita mewakili seberapa berartinya memiliki pengguna bagi aplikasi kita. Kita akan memiliki bidang untuk alamat surel, kata sandi, dan nama. Di aplikasi, Anda mungkin memutuskan bahwa Anda menginginkan lebih banyak informasi untuk disimpan per pengguna. Anda dapat menambah hal-hal seperti ulang tahun, foto profil, lokasi, atau preferensi pengguna apa pun.

      Model yang diciptakan dalam Flask-SQLAlchemy diwakili oleh kelas-kelas yang kemudian diterjemahkan ke tabel-tabel di dalam basis data. Atribut dari kelas-kelas itu lalu berubah menjadi kolom-kolom untuk tabel tersebut.

      Mari kita lanjutkan dan ciptakan model pengguna itu:

      Kode ini menciptakan model pengguna dengan kolom untuk id, email, password, dan name:

      project/models.py

      from . import db
      
      class User(db.Model):
          id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
          email = db.Column(db.String(100), unique=True)
          password = db.Column(db.String(100))
          name = db.Column(db.String(1000))
      

      Karena kini Anda telah menciptakan model pengguna, Anda dapat melanjutkan ke mengonfigurasi basis data.

      Langkah 6 — Mengonfigurasi Basis Data

      Seperti yang tercantum di dalam Prasyarat, kita akan menggunakan basis data SQLite. Kita dapat menciptakan basis data SQLite sendiri, tetapi mari kita biarkan Flask-SQLAlchemy yang melakukannya untuk kita. Kita telah memiliki jalur basis data yang ditentukan dalam berkas __init__.py, sehingga kita hanya perlu memberi tahu Flask-SQLAlchemy untuk menciptakan basis data di Python REPL.

      Jika Anda menghentikan aplikasi dan membuka Python REPL, kita dapat menciptakan basis data menggunakan metode create_all pada objek db. Pastikan Anda masih berada di lingkungan virtual dan di dalam direktori >flask_auth_app.

      • from project import db, create_app
      • db.create_all(app=create_app()) # pass the create_app result so Flask-SQLAlchemy gets the configuration.

      Catatan: Jika menggunakan penafsir Python merupakan hal baru bagi Anda, Anda dapat melihat dokumentasi resmi.

      Sekarang Anda akan melihat berkas db.sqlite di dalam direktori proyek. Basis data ini akan memiliki tabel pengguna kita di dalamnya.

      Langkah 7 — Menyiapkan Fungsi Otorisasi

      Untuk fungsi pendaftaran, kita akan mengambil data yang diketik pengguna ke dalam formulir dan menambahkannya ke dalam basis data kita. Sebelum menambahkannya, kita perlu memastikan bahwa pengguna tidak ada di basis data. Jika pengguna tidak ada, kita perlu memastikan kita melakukan hash kata sandi sebelum menempatkannya ke dalam basis data karena kita tidak mau kata sandi kita disimpan dalam teks polos.

      Mari kita mulai dengan menambahkan fungsi kedua untuk menangani data formulir POST. Dalam fungsi ini, kita akan mengumpulkan data yang diwariskan dari pengguna terlebih dahulu.

      Ciptakan fungsi dan tambahkan pengalihan di bagian bawah. Perintah ini akan memberikan pengalaman pengguna dari pendaftaran yang berhasil dan diarahkan ke Laman Log Masuk.

      Perbarui auth.py dengan memodifikasi baris impor dan menerapkan signup_post:

      project/auth.py

      from flask import Blueprint, render_template, redirect, url_for
      ...
      @auth.route('/signup', methods=['POST'])
      def signup_post():
          # code to validate and add user to database goes here
          return redirect(url_for('auth.login'))
      

      Sekarang, mari kita tambahkan sisa kode yang diperlukan untuk mendaftarkan pengguna.

      Untuk memulai, kita harus menggunakan objek yang diminta untuk mendapatkan data formulir.

      Lanjutkan untuk memperbarui auth.py dengan menambahkan impor dan menerapkan signup_post:

      auth.py

      from flask import Blueprint, render_template, redirect, url_for, request
      from werkzeug.security import generate_password_hash, check_password_hash
      from .models import User
      from . import db
      ...
      @auth.route('/signup', methods=['POST'])
      def signup_post():
          email = request.form.get('email')
          name = request.form.get('name')
          password = request.form.get('password')
      
          user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database
      
          if user: # if a user is found, we want to redirect back to signup page so user can try again
              return redirect(url_for('auth.signup'))
      
          # create a new user with the form data. Hash the password so the plaintext version isn't saved.
          new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))
      
          # add the new user to the database
          db.session.add(new_user)
          db.session.commit()
      
          return redirect(url_for('auth.login'))
      

      Catatan: Menyimpan kata sandi dalam teks polos adalah praktik keamanan yang buruk. Anda umumnya akan ingin memanfaatkan algoritma hash yang kompleks dan suatu garam kata sandi agar kata sandi tetap aman.

      Langkah 8 — Menguji Metode Pendaftaran

      Karena kini kita telah menyelesaikan metode pendaftaran, kita seharusnya dapat menciptakan pengguna baru. Gunakan formulir untuk menciptakan pengguna.

      Ada dua cara untuk memverifikasi jika pendaftaran berhasil: Anda dapat menggunakan penampil basis data untuk melihat baris yang ditambahkan ke tabel, atau Anda dapat mencoba mendaftar dengan alamat surel yang sama lagi, dan jika Anda mendapat pesan kesalahan, Anda tahu bahwa surel pertama telah disimpan dengan benar. Mari kita coba pendekatan itu.

      Kita dapat menambahkan kode untuk menginformasikan pengguna bahwa surel sudah ada dan memberi tahu mereka untuk pergi ke laman log masuk. Dengan memanggil fungsi flash, kita akan mengirim pesan ke permintaan selanjutnya, yang dalam hal ini adalah pengalihan. Laman yang kita kunjungi akan memiliki akses ke pesan itu di dalam templat.

      Pertama-tama, kita tambahkan flash sebelum kita mengalihkan kembali ke laman pendaftaran.

      project/auth.py

      from flask import Blueprint, render_template, redirect, url_for, request, flash
      ...
      @auth.route('/signup', methods=['POST'])
      def signup_post():
          ...
          if user: # if a user is found, we want to redirect back to signup page so user can try again
              flash('Email address already exists')
              return redirect(url_for('auth.signup'))
      

      Untuk mendapatkan pesan flash di dalam templat, kita dapat menambahkan kode ini di atas formulir. Ini akan menampilkan pesan secara langsung di atas formulir.

      project/templates/signup.html

      ...
      {% with messages = get_flashed_messages() %}
      {% if messages %}
          <div class="notification is-danger">
              {{ messages[0] }}. Go to <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.login') }}">login page</a>.
          </div>
      {% endif %}
      {% endwith %}
      <form method="POST" action="/signup">
      

      Kotak pendaftaran menampilkan pesan

      Langkah 9 — Menambahkan Metode Log Masuk

      Metode log masuk mirip dengan fungsi pendaftaran dalam hal kita akan mengambil informasi pengguna dan melakukan sesuatu dengannya. Dalam kasus ini, kita akan membandingkan alamat surel yang dimasukkan untuk melihat apakah alamat itu ada di dalam basis data. Jika demikian, kita akan menguji kata sandi yang disediakan pengguna dengan melakukan hash kata sandi yang diberikan pengguna dan membandingkannya dengan kata sandi yang telah melalui proses hash yang ada di dalam basis data. Kita tahu pengguna telah memasukkan kata sandi yang benar saat kedua kata sandi yang telah melalui proses hash sesuai.

      Setelah pengguna melewati pemeriksaan kata sandi, kita tahu bahwa pengguna itu memiliki kredensial yang benar dan kita dapat membuat mereka log masuk menggunakan Flask-Login. Dengan memanggil login_user, Flask-Login akan menciptakan sesi untuk pengguna tersebut yang akan tetap aktif selama pengguna tetap log masuk, yang akan memungkinkan pengguna untuk melihat laman terlindungi.

      Kita dapat memulai dengan rute baru untuk menangani data POSTed. Kita akan mengalihkan ke laman profil saat pengguna berhasil log masuk:

      project/auth.py

      ...
      @auth.route('/login', methods=['POST'])
      def login_post():
          # login code goes here
          return redirect(url_for('main.profile'))
      

      Sekarang, kita perlu memverifikasi apakah pengguna memiliki kredensial yang benar:

      project/auth.py

      ...
      @auth.route('/login', methods=['POST'])
      def login_post():
          email = request.form.get('email')
          password = request.form.get('password')
          remember = True if request.form.get('remember') else False
      
          user = User.query.filter_by(email=email).first()
      
          # check if the user actually exists
          # take the user-supplied password, hash it, and compare it to the hashed password in the database
          if not user or not check_password_hash(user.password, password):
              flash('Please check your login details and try again.')
              return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page
      
          # if the above check passes, then we know the user has the right credentials
          return redirect(url_for('main.profile'))
      

      Mari kita tambahkan blok ke dalam templat sehingga pengguna dapat melihat pesan flash. Seperti formulir pendaftaran, mari kita tambahkan pesan kesalahan potensial secara langsung di atas formulir:

      project/templates/login.html

      ...
      {% with messages = get_flashed_messages() %}
      {% if messages %}
          <div class="notification is-danger">
              {{ messages[0] }}
          </div>
      {% endif %}
      {% endwith %}
      <form method="POST" action="/login">
      

      Kini kita telah memiliki kemampuan untuk mengatakan pengguna telah berhasil log masuk, tetapi pengguna tidak masuk ke mana pun. Ini adalah saat kita menggunakan Flask-Login untuk mengelola sesi pengguna.

      Sebelum kita memulai, kita memerlukan beberapa hal agar Flask-Login bekerja. Mulai dengan menambahkan UserMixin ke model Pengguna Anda. UserMixin akan menambahkan atribut Flask-Login ke model sehingga Flask-Login akan dapat bekerja dengannya.

      models.py

      from flask_login import UserMixin
      from . import db
      
      class User(UserMixin, db.Model):
          id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
          email = db.Column(db.String(100), unique=True)
          password = db.Column(db.String(100))
          name = db.Column(db.String(1000))
      

      Kemudian, kita perlu menentukan pemuat pengguna kita. Pemuat pengguna memberi tahu Flask-Login cara menemukan pengguna tertentu dari ID yang disimpan di dalam kuki sesi mereka. Kita dapat menambahkan ini ke dalam fungsi create_app bersama dengan kode init untuk Flask-Login:

      project/__init__.py

      ...
      from flask_login import LoginManager
      ...
      def create_app():
          ...
          db.init_app(app)
      
          login_manager = LoginManager()
          login_manager.login_view = 'auth.login'
          login_manager.init_app(app)
      
          from .models import User
      
          @login_manager.user_loader
          def load_user(user_id):
              # since the user_id is just the primary key of our user table, use it in the query for the user
              return User.query.get(int(user_id))
      

      Terakhir, kita dapat menambahkan fungsi login_user sebelum kita mengalihkan ke laman profil untuk menciptakan sesi:

      project/auth.py

      from flask_login import login_user
      from .models import User
      ...
      @auth.route('/login', methods=['POST'])
      def login_post():
          ...
          # if the above check passes, then we know the user has the right credentials
          login_user(user, remember=remember)
          return redirect(url_for('main.profile'))
      

      Dengan penyiapan Flask-Login, kita dapat menggunakan rute /login. Ketika semuanya disiapkan dengan benar, Anda akan melihat laman profil.

      Laman profil dengan

      Langkah 10 — Melindungi Laman

      Jika nama Anda bukan Anthony, Anda akan melihat bahwa nama Anda salah. Kita ingin profil menampilkan nama yang ada di dalam basis data. Pertama-tama, kita perlu melindungi laman itu, kemudian mengakses data pengguna untuk mendapatkan namanya.

      Untuk melindungi laman saat menggunakan Flask-Login, kita menambahkan dekorator @login_required antara rute dan fungsi. Ini akan mencegah pengguna yang tidak log masuk untuk melihat rute. Jika pengguna tidak log masuk, pengguna akan dialihkan ke laman log masuk, sesuai konfigurasi Flask-Login.

      Dengan rute yang dilengkapi oleh dekorator @login_required, kita akan memiliki kemampuan untuk menggunakan objek current_user di dalam fungsi. current_user ini mewakili pengguna dari basis data, dan kita dapat mengakses semua atribut pengguna itu dengan notasi titik. Misalnya, current_user.email, current_user.password, dan current_user.name, serta current_user.id akan memberikan nilai sebenarnya yang disimpan di dalam basis data bagi pengguna yang log masuk.

      Mari kita gunakan nama pengguna saat ini dan mengirimkannya ke templat. Kemudian, kita akan menggunakan nama itu dan menampilkan nilainya.

      project/main.py

      from flask_login import login_required, current_user
      ...
      @main.route('/profile')
      @login_required
      def profile():
          return render_template('profile.html', name=current_user.name)
      

      Lalu, dalam berkas profile.html, perbarui laman untuk menampilkan nilai name:

      project/templates/profile.html

      ...
      <h1 class="title">
        Welcome, {{ name }}!
      </h1>
      

      Setelah kita mengunjungi laman profil, kita akan melihat bahwa nama pengguna muncul.

      Laman sambutan pengguna dengan nama pengguna yang sedang log masuk saat ini

      Hal terakhir yang dapat kita lakukan adalah memperbarui tampilan log keluar. Kita dapat memanggil fungsi logout_user dalam suatu rute untuk log keluar. Kita memiliki dekorator @login_required karena tidak masuk akal untuk mengeluarkan pengguna yang sebelumnya tidak log masuk.

      project/auth.py

      from flask_login import login_user, logout_user, login_required
      ...
      @auth.route('/logout')
      @login_required
      def logout():
          logout_user()
          return redirect(url_for('main.index'))
      

      Setelah kita log keluar dan mencoba melihat laman profil lagi, kita melihat pesan kesalahan muncul. Ini karena Flask-Login melakukan flash pesan untuk kita ketika pengguna tidak diizinkan untuk mengakses laman.

      Laman log masuk dengan pesan menunjukkan bahwa pengguna harus log masuk untuk mengakses laman

      Satu hal terakhir yang dapat kita lakukan adalah memasukkan pernyataan if di dalam templat untuk menampilkan hanya tautan yang relevan dengan pengguna. Jadi, sebelum pengguna log masuk, mereka akan memiliki opsi untuk log masuk atau mendaftar. Setelah mereka log masuk, mereka dapat mengunjungi profil mereka atau log keluar:

      templates/base.html

      ...
      <div class="navbar-end">
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.index') }}" class="navbar-item">
              Home
          </a>
          {% if current_user.is_authenticated %}
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("main.profile') }}" class="navbar-item">
              Profile
          </a>
          {% endif %}
          {% if not current_user.is_authenticated %}
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.login') }}" class="navbar-item">
              Login
          </a>
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.signup') }}" class="navbar-item">
              Sign Up
          </a>
          {% endif %}
          {% if current_user.is_authenticated %}
          <a href="https://www.digitalocean.com/community/tutorials/{{ url_for("auth.logout') }}" class="navbar-item">
              Logout
          </a>
          {% endif %}
      </div>
      

      Laman beranda dengan navigasi Home, Login, dan Sign Up di bagian atas layar

      Dengan demikian, Anda telah berhasil membangun aplikasi Anda dengan autentikasi.

      Kesimpulan

      Kita telah menggunakan Flask-Login dan Flask-SQLAlchemy untuk membangun sistem log masuk pada aplikasi. Kita telah membahas cara melakukan autentikasi pengguna dengan menciptakan model pengguna dan menyimpan informasi pengguna terlebih dahulu. Kemudian, kita harus memverifikasi bahwa kata sandi pengguna adalah benar dengan melakukan hash kata sandi dari formulir dan membandingkannya dengan yang disimpan di basis data. Terakhir, kita menambahkan otorisasi ke aplikasi kita menggunakan dekorator @login_required di laman profil sehingga hanya pengguna yang sedang log masuk yang dapat melihat laman itu.

      Yang kita ciptakan dalam tutorial ini akan cukup untuk aplikasi yang kecil, tetapi jika Anda ingin memiliki fungsionalitas lebih banyak sejak awal, Anda mungkin dapat mempertimbangkan untuk menggunakan baik pustaka Flask-User atau Flask-Security, yang mana keduanya dibangun di atas pustaka Flask-Login.



      Source link

      Cara Menambah Ruang Swap pada Ubuntu 20.04


      Pengantar

      Salah satu cara untuk menghindari kesalahan kehabisan memori dalam aplikasi adalah dengan menambahkan sejumlah ruang swap ke server Anda. Dalam panduan ini, kita akan membahas cara menambah suatu berkas swap ke server Ubuntu 20.04.

      Peringatan: Meskipun biasanya swap disarankan untuk sistem yang menggunakan hard drive berputar tradisional, harap diperhatikan bahwa melakukan swap pada SSD dapat menyebabkan masalah terkait degradasi perangkat keras seiring waktu. Karena itu, kami tidak menyarankan untuk mengaktifkan swap pada DigitalOcean atau penyedia lainnya yang menggunakan penyimpanan SSD.

      Apa itu Swap?

      Swap adalah bagian dari penyimpanan hard drive yang telah disisihkan pada sistem operasi untuk secara sementara menyimpan data yang tidak dapat lagi disimpan di RAM. Ini memungkinkan Anda untuk menambah jumlah informasi yang dapat disimpan oleh server Anda di dalam memori yang sedang bekerja, dengan beberapa peringatan. Ruang swap pada hard drive akan digunakan terutama saat tidak ada lagi ruang yang cukup di RAM untuk menyimpan data aplikasi yang sedang digunakan.

      Informasi yang ditulis ke diska akan lebih lambat secara signifikan dibandingkan informasi yang disimpan dalam RAM, tetapi sistem operasi akan lebih memilih untuk tetap menjalankan data aplikasi dalam memori dan menggunakan swap untuk data yang lebih tua. Secara garis besar, memiliki ruang swap sebagai pilihan alternatif saat RAM sistem Anda habis dapat menjadi jaring pengaman yang baik terhadap eksepsi kehabisan memori pada sistem dengan penyimpanan non-SSD.

      Langkah 1 – Memeriksa Sistem untuk Informasi Swap

      Sebelum memulai, kita dapat memeriksa apakah sistem sudah memiliki sebagian ruang swap yang tersedia. Dimungkinkan untuk memiliki beberapa berkas swap atau partisi swap, tetapi pada umumnya satu sudah cukup.

      Kita dapat melihat apakah sistem memiliki swap yang terkonfigurasi dengan mengetik:

      Jika Anda tidak mendapat keluaran apa pun, ini berarti sistem Anda tidak memiliki ruang swap yang tersedia saat ini.

      Anda dapat memverifikasi bahwa tidak ada swap yang aktif dengan menggunakan utilitas free:

      Output

      total used free shared buff/cache available Mem: 981Mi 122Mi 647Mi 0.0Ki 211Mi 714Mi Swap: 0B 0B 0B

      Seperti yang Anda lihat di baris Swap pada keluaran, tidak ada swap yang aktif pada sistem.

      Langkah 2 – Memeriksa Ruang Tersedia pada Partisi Hard Drive

      Sebelum menciptakan berkas swap, kita akan memeriksa penggunaan diska saat ini untuk memastikan kita memiliki cukup ruang. Lakukan ini dengan mengetik:

      Output

      Filesystem Size Used Avail Use% Mounted on udev 474M 0 474M 0% /dev tmpfs 99M 932K 98M 1% /run /dev/vda1 25G 1.4G 23G 7% / tmpfs 491M 0 491M 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 491M 0 491M 0% /sys/fs/cgroup /dev/vda15 105M 3.9M 101M 4% /boot/efi /dev/loop0 55M 55M 0 100% /snap/core18/1705 /dev/loop1 69M 69M 0 100% /snap/lxd/14804 /dev/loop2 28M 28M 0 100% /snap/snapd/7264 tmpfs 99M 0 99M 0% /run/user/1000

      Perangkat dengan / di dalam kolom Mounted on adalah diska kita dalam kasus ini. Kita memiliki banyak ruang yang tersedia dalam contoh ini (hanya digunakan 1,4 G). Penggunaan Anda mungkin akan berbeda.

      Meskipun ada banyak pendapat tentang ukuran ruang swap yang sesuai, hal itu benar-benar bergantung pada preferensi pribadi dan persyaratan aplikasi Anda. Secara umum, jumlah yang sama atau dua kali dari jumlah RAM pada sistem Anda adalah titik awal yang baik. Patokan yang baik lainnya adalah swap apa pun di atas 4 G mungkin tidak diperlukan jika Anda hanya menggunakannya sebagai pilihan alternatif RAM.

      Langkah 3 – Menciptakan Berkas Swap

      Kini setelah kita mengetahui ruang hard drive yang tersedia, kita dapat menciptakan berkas swap di sistem kita. Kita akan mengalokasikan berkas dengan ukuran yang diinginkan yang bernama swapfile di direktori root (/) kita.

      Cara terbaik untuk menciptakan berkas swap adalah dengan program fallocate. Perintah ini seketika menciptakan berkas dengan ukuran yang ditentukan.

      Karena server dalam contoh kita memiliki 1 G RAM, kita akan menciptakan berkas 1 G dalam panduan ini. Sesuaikan ini untuk memenuhi kebutuhan server Anda:

      • sudo fallocate -l 1G /swapfile

      Kita dapat memverifikasi bahwa jumlah ruang yang benar telah disiapkan dengan mengetik:

      • -rw-r--r-- 1 root root 1.0G Apr 25 11:14 /swapfile

      Berkas telah dibuat dengan menyisihkan jumlah ruang yang benar.

      Langkah 4 – Mengaktifkan Berkas Swap

      Karena sudah memiliki berkas dengan ukuran yang benar, kita perlu mengubahnya menjadi ruang swap yang sesungguhnya.

      Pertama-tama, kita perlu untuk mengunci izin berkas sehingga hanya pengguna dengan privilese root yang dapat membaca konten. Ini mencegah pengguna normal untuk dapat mengakses berkas, yang akan memiliki implikasi keamanan yang signifikan.

      Buat berkas hanya dapat diakses oleh root dengan mengetik:

      Lakukan verifikasi perubahan izin dengan mengetik:

      Output

      -rw------- 1 root root 1.0G Apr 25 11:14 /swapfile

      Seperti yang terlihat, hanya pengguna root yang memiliki bendera baca dan tulis yang diaktifkan.

      Sekarang kita dapat menandai berkas sebagai ruang swap dengan mengetik:

      Output

      Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes) no label, UUID=6e965805-2ab9-450f-aed6-577e74089dbf

      Setelah menandai berkas, kita dapat mengaktifkan berkas swap, yang mengizinkan sistem kita untuk mulai menggunakannya:

      Lakukan verifikasi bahwa swap tersedia dengan mengetik:

      Output

      NAME TYPE SIZE USED PRIO /swapfile file 1024M 0B -2

      Kita dapat memeriksa keluaran utilitas free lagi untuk menguatkan temuan kita:

      Output

      total used free shared buff/cache available Mem: 981Mi 123Mi 644Mi 0.0Ki 213Mi 714Mi Swap: 1.0Gi 0B 1.0Gi

      Swap telah berhasil disiapkan dan sistem operasi kita akan mulai menggunakannya ketika diperlukan.

      Langkah 5 – Membuat Berkas Swap Jadi Permanen

      Perubahan terbaru kita telah mengaktifkan berkas swap untuk sesi ini. Namun, jika kita melakukan boot ulang, server tidak akan mempertahankan pengaturan swap secara otomatis. Kita dapat mengubah ini dengan menambahkan berkas swap ke berkas /etc/fstab.

      Cadangkan berkas /etc/fstab seandainya ada kesalahan:

      • sudo cp /etc/fstab /etc/fstab.bak

      Tambahkan informasi berkas swap di akhir berkas /etc/fstab dengan mengetik:

      • echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

      Selanjutnya, kita akan meninjau beberapa pengaturan yang dapat kita perbarui untuk menyetel ruang swap.

      Langkah 6 – Menyetel Pengaturan Swap Anda

      Ada beberapa opsi yang dapat Anda atur agar berdampak pada kinerja sistem Anda saat berurusan dengan swap.

      Menyesuaikan Properti Swappiness

      Parameter swappiness mengonfigurasi seberapa sering sistem Anda melakukan swap data dari RAM ke ruang swap. Ini adalah nilai antara 0 dan 100 yang mewakili persentase.

      Dengan nilai yang dekat dengan nol, kernel tidak akan melakukan swap data ke diska kecuali benar-benar diperlukan. Ingat, interaksi dengan berkas swap adalah hal “mahal” yang dalam hal ini berarti memakan waktu lebih lama daripada interaksi dengan RAM dan dapat menyebabkan pengurangan kinerja yang signifikan. Memberi tahu sistem untuk tidak terlalu banyak mengandalkan swap secara umum akan membuat sistem Anda lebih cepat.

      Nilai yang lebih dekat dengan 100 akan mencoba menaruh lebih banyak data ke dalam swap sebagai upaya untuk menjaga lebih banyak ruang RAM yang lowong. Tergantung profil memori aplikasi atau kegunaan server, ini mungkin pilihan yang lebih baik dalam beberapa kasus.

      Kita dapat melihat nilai swappiness saat ini dengan mengetik:

      • cat /proc/sys/vm/swappiness

      Output

      60

      Untuk Desktop, pengaturan swappiness 60 bukanlah nilai yang buruk. Untuk server, Anda mungkin ingin memindahkannya lebih dekat dengan 0.

      Kita dapat mengatur swappiness ke nilai yang berbeda dengan menggunakan perintah sysctl.

      Misalnya, untuk mengatur swappiness menjadi 10, kita dapat mengetik:

      • sudo sysctl vm.swappiness=10

      Output

      vm.swappiness = 10

      Pengaturan ini akan terus ada hingga boot ulang selanjutnya. Kita dapat mengatur nilai ini secara otomatis saat memulai ulang dengan menambahkan baris ke berkas /etc/sysctl.conf:

      • sudo nano /etc/sysctl.conf

      Di bagian bawah, Anda dapat menambahkan:

      /etc/sysctl.conf

      vm.swappiness=10
      

      Simpan dan tutup berkas saat Anda sudah selesai.

      Menyesuaikan Pengaturan Cache Pressure

      Nilai terkait lainnya yang mungkin Anda ingin modifikasi adalah vfs_cache_pressure. Pengaturan ini mengonfigurasi seberapa banyak sistem akan memilih untuk melakukan cache pada inode dan informasi dentry dibandingkan data lainnya.

      Pada dasarnya, ini adalah data akses tentang sistem berkas. Secara umum, ini sangat sulit untuk dicari dan sangat sering diminta, jadi sebaiknya sistem Anda melakukan cache. Anda dapat melihat nilai saat ini dengan melakukan kueri sistem berkas proc lagi:

      • cat /proc/sys/vm/vfs_cache_pressure

      Output

      100

      Dalam konfigurasi saat ini, sistem kita menghapus informasi inode dari cache dengan terlalu cepat. Kita dapat mengatur ini ke pengaturan yang lebih konservatif seperti 50 dengan mengetik:

      • sudo sysctl vm.vfs_cache_pressure=50

      Output

      vm.vfs_cache_pressure = 50

      Sekali lagi, ini hanya valid untuk sesi kita saat ini. Kita dapat mengubah hal itu dengan menambahkannya ke berkas konfigurasi seperti yang kita lakukan dengan pengaturan swappiness:

      • sudo nano /etc/sysctl.conf

      Di bagian bawah, tambahkan baris yang menentukan nilai baru Anda:

      /etc/sysctl.conf

      vm.vfs_cache_pressure=50
      

      Simpan dan tutup berkas saat Anda sudah selesai.

      Kesimpulan

      Mengikuti langkah-langkah dalam panduan ini akan memberi Anda sebagian ruang bernapas dalam kasus terkait eksepsi kehabisan memori. Ruang swap dapat menjadi sangat berguna untuk menghindari sebagian masalah umum ini.

      Jika Anda menjumpai pesan kesalahan OOM (kehabisan memori), atau jika Anda menemukan bahwa sistem tidak dapat menggunakan aplikasi yang Anda perlukan, solusi terbaiknya adalah dengan mengoptimalkan konfigurasi aplikasi atau meningkatkan server.



      Source link