"""TIES4080 pääteohjaus 3: kirjautuminen omalla sivullaan. Sama asia kuin oma.py:ssä, mutta kirjautumislomake ja sen käsittelijä ovat eri osoitteissa. Kannattaa katsoa selaimen kehittäjätyökalujen verkkovälilehdeltä, miten osoitteiden välillä liikutaan lomakkeen lähettämisen jälkeen. """ import os from functools import wraps from flask import Flask, flash, redirect, render_template, request, session, url_for from werkzeug.security import check_password_hash app = Flask(__name__) # Salainen avain allekirjoittaa sessioevästeen. Sen tietävä voi väärentää # session, joten avainta ei kirjoiteta lähdekoodiin eikä versionhallintaan. # users.jyu.fi-palvelimella ei voi asettaa omia ympäristömuuttujia, joten avain # luetaan tiedostosta, joka on www-hakemiston ulkopuolella samassa kansiossa # tietokannan kanssa. # # Tiedosto luodaan kerran komennoilla: # python3 -c "import secrets; print(secrets.token_hex(32))" > ~/public_html/hidden/avain.txt # chmod 600 ~/public_html/hidden/avain.txt AVAINTIEDOSTO = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "..", "hidden", "avain.txt") def lue_salainen_avain(polku): try: with open(polku, encoding="UTF-8") as tiedosto: avain = tiedosto.read().strip() except OSError as virhe: raise RuntimeError( f"Salaista avainta ei saada luettua tiedostosta {polku}. " "Luo tiedosto komennolla: " "python3 -c \"import secrets; print(secrets.token_hex(32))\" > avain.txt" ) from virhe if not avain: raise RuntimeError(f"Avaintiedosto {polku} on tyhjä.") return avain app.secret_key = lue_salainen_avain(AVAINTIEDOSTO) app.config.update( SESSION_COOKIE_SAMESITE="Lax", SESSION_COOKIE_SECURE=True, ) TUNNUS = "ties4080" TARKISTE = ("scrypt:32768:8:1$kS80LL7mVNyr7pwB$ed17bfdc0021bfc34d0fc2d3db0709" "760d77d29ca3d9560734aa14e30031eb3d31fc1d020155745330b9df3c780fbc" "4f3677a0e0f9f49410a52541afd73928b4") def auth(f): @wraps(f) def kaaritty(*args, **kwargs): if "kirjautunut" not in session: return redirect(url_for("start"), code=303) return f(*args, **kwargs) return kaaritty @app.get("/") def start(): """Sivu, jolla on pelkkä kirjautumislomake.""" return render_template("kirjaudu2.html") @app.post("/kirjaudu") def kirjaudu(): tunnus = request.form.get("tunnus", "").strip() salasana = request.form.get("salasana", "") if tunnus == TUNNUS and check_password_hash(TARKISTE, salasana): session.clear() session["kirjautunut"] = tunnus return redirect(url_for("kirjautunut"), code=303) # Virheilmoitus välitetään flash-viestinä, koska vastaus on uudelleenohjaus. flash("Tunnus tai salasana on väärin.") return redirect(url_for("start"), code=303) @app.post("/kirjaudu-ulos") def kirjaudu_ulos(): session.clear() return redirect(url_for("start"), code=303) @app.get("/kirjautunut") @auth def kirjautunut(): return render_template("kirjautunut.html", tunnus=session["kirjautunut"]) if __name__ == "__main__": app.run(debug=True)