Skip to content

38. Toepassingsopdracht: versie 18

38.1. Implementatie

Image

Het bestand [impots/http-servers/13] wordt in eerste instantie verkregen door het bestand [impots/http-servers/12] te kopiëren en vervolgens gedeeltelijk te wijzigen.

We beginnen met het toevoegen van een nieuwe parameter in het bestand [configs/parameters]:


…        
         # CSRF-token
        "with_csrftoken"False,
        # beheerde databases MySQL (mysql), PostgreSQL (pgres)
        "databases"["mysql""pgres"],
        # voorvoegsel van de URL van de applicatie
        # stel de tekenreeks in op leeg als je geen prefix wilt, of anders /prefix
        "prefix_url""/do",
        # hoofd-URL van de Apache-server – laat de tekenreeks leeg voor uitvoering buiten Apache
        "application_root""/impots"

Op regel 10 staat de parameter [application_root], die de alias WSGI van de virtuele Apache-server vertegenwoordigt.

Met deze parameter kunnen we de instructie van [responses/HtmlResponse] corrigeren die de fout had veroorzaakt:

Image



# nu moet de omleidingscode URL worden gegenereerd, zonder het token CSRF te vergeten als daarom wordt gevraagd
        if config['parameters']['with_csrftoken']:
            csrf_token = f"/{generate_csrf()}"
        else:
            csrf_token = ""

        # omleidingsantwoord
        return redirect(f"{config['parameters']['application_root']}{config['parameters']['prefix_url']}{ads['to']}{csrf_token}")
, status.HTTP_302_FOUND
  • regel 9: we hebben de root van de applicatie toegevoegd aan het begin van het omleidingsdoel URL;

We moeten ook alle fragmenten corrigeren, zodat de URL die ze bevatten, beginnen met de root van de applicatie (of alias WSGI):

Image

Het fragment [v-authentification]


<!-- formulier HTML – we verzenden de waarden met de actie [authentifier-utilisateur] -->
<form method="post" action="{{modèle.application_root}}{{modèle.prefix_url}}/authentifier-utilisateur{{modèle.csrf_token}}"
>

    <!-- titel -->
    <div class="alert alert-primary" role="alert">
        <h4>Veuillez vous authentifier</h4>
    </div>


</form>

Het fragment [v-calcul-impot]


<!-- formulier HTML verzonden -->
<form method="post" action="{{modèle.application_root}}{{modèle.prefix_url}}/calculer-impot{{modèle.csrf_token}}">
    <!-- bericht met 12 kolommen op een blauwe achtergrond -->
    

</form>

Het fragment [v-liste-simulations]




{% if modèle.simulations is defined and modèle.simulations|length!=0 %}


<!-- simulatietabel -->
<table class="table table-sm table-hover table-striped">
    
    <tr>
        <th scope="row">{{simulation.id}}</th>
        <td>{{simulation.marié}}</td>
        <td>{{simulation.enfants}}</td>
        <td>{{simulation.salaire}}</td>
        <td>{{simulation.impôt}}</td>
        <td>{{simulation.surcôte}}</td>
        <td>{{simulation.décôte}}</td>
        <td>{{simulation.réduction}}</td>
        <td>{{simulation.taux}}</td>
        <td><a href="{{modèle.application_root}}{{modèle.prefix_url}}/supprimer-simulation/{{simulation.id}}{{modèle.csrf_token}}">Supprimer</a></td>
    </tr>
    {% endfor %}
    </tr>
    </tbody>
</table>
{% endif %}

Het fragment [v-menu]


<!-- Bootstrap-menu -->
<nav class="nav flex-column">
    <!-- weergave van een lijst met links HTML -->
    {% for optionMenu in modèle.optionsMenu %}
    <a class="nav-link" href="{{modèle.application_root}}{{modèle.prefix_url}}{{optionMenu.url}}{{modèle.csrf_token}}">{{optionMenu.text}}</a>
    {% endfor %}
</nav>

De bovenstaande fragmenten maken allemaal gebruik van het sjabloon [modèle.application_root]. Op dit moment bestaat de sleutel [application_root] niet in de sjablonen die door de sjabloonklassen worden gegenereerd.

Image

De klasse [AbstractBaseModelForView], de bovenliggende klasse van alle klassen die een sjabloon genereren, ziet er als volgt uit:


from abc import abstractmethod

from flask import Request
from flask_wtf.csrf import generate_csrf
from werkzeug.local import LocalProxy

from InterfaceModelForView import InterfaceModelForView

class AbstractBaseModelForView(InterfaceModelForView):

    @abstractmethod
    def get_model_for_view(self, request: Request, session: LocalProxy, config: dict, résultat: dict) -> dict:
        pass

    def update_model(self, modèle: dict, config: dict):
        # berekening van het token CSRF
        if config['parameters']['with_csrftoken']:
            csrf_token = f"/{generate_csrf()}"
        else:
            csrf_token = ""
        # bijwerken van het als parameter doorgegeven sjabloon
        modèle.update({
            # CSRF-token
            'csrf_token': csrf_token,
            # prefix_url
            'prefix_url': configQZXW2HTMLBWyJwYXJhbWV0ZXJzIl0ZQXQZXW2HTMLBWyJwcmVmaXhfdXJsIl0ZQX,
            # application_root
            'application_root': configQZXW2HTMLBWyJwYXJhbWV0ZXJzIl0ZQXQZXW2HTMLBWyJhcHBsaWNhdGlvbl9yb290Il0ZQX,
        })
  • regel 15: de methode [update_model] heeft als taak weergaven in het sjabloon op te nemen:
    • regel 24: het token CSRF;
    • regel 26: het voorvoegsel van URL;
    • regel 28: de hoofdmap van de applicatie of alias WSGI;

De vier dochterklassen roepen de bovenliggende klasse aan met de volgende code:



        # mogelijke acties vanuit de weergave
        modèle['actions_possibles'] = ["afficher-vue-authentification""authentifier-utilisateur"]

        # afwerking van het model door de bovenliggende klasse
        super().update_model(modèle, config)

        # het model wordt weergegeven
        return modèle
  • regel 6: elke dochterklasse roept haar bovenliggende klasse aan om het door haar aangemaakte model bij te werken;

Versie 18 is klaar. We nemen de twee virtuele Apache-servers uit versie 17 over en passen ze aan:

Image

De twee bestanden [flask-impots-withXX.conf] worden op slechts één punt gewijzigd:


# map van het .wsgi-script
define ROOT "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/impots/http-servers/13/apache"

# naam van de website die door dit bestand wordt geconfigureerd
# hier zal deze flask-impots-withmysql heten
# de URL zullen van het type http(s)://flask-impots-withmysql/pad zijn
define SITE "flask-impots-withmysql"

# voeg het adres IP 127.0.0.1 voor de site SITE toe aan c:/windows/system32/drivers/etc/hosts

# voeg hier de paden toe naar de te gebruiken Python-bibliotheken – scheid ze met komma’s
# hier de bibliotheken van een virtuele Python-omgeving
WSGIPythonPath  "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/venv/lib/site-packages"

# Python Home – alleen nodig als er meerdere versies van Python zijn geïnstalleerd
# WSGIPythonHome "C:/Program Files/Python38"

# URL HTTP
<VirtualHost *:80>
    # met de alias / zullen de URL de vorm /{prefixe_url}/action/... hebben
    # met de alias /impots zullen de URL de vorm /impots/{prefixe_url}/action/... aannemen
    # waarbij [prefixe_url] is gedefinieerd in parameters.py
    WSGIScriptAlias /impots "${ROOT}/main_withmysql.wsgi"
    …
</VirtualHost>

# URL beveiligd met HTTPS
<VirtualHost *:443>
    # met de alias / zullen de URL de vorm /{prefixe_url}/action/... hebben
    # met de alias /impots zullen de URL de vorm /impots/{prefixe_url}/action/... aannemen
    # waarbij [prefixe_url] is gedefinieerd in parameters.py
    WSGIScriptAlias /impots "${ROOT}/main_withmysql.wsgi"
    ..

</VirtualHost>
  • op regel 12 wordt nu de map [impots/http-servers/13/apache] gebruikt.

We zijn klaar om versie 18 op Apache te testen. De configuratie is als volgt:

  • de alias WSGI is /impots in beide configuratiebestanden van de virtuele servers;
  • in het configuratiebestand [configs/parameters] zijn de instellingen als volgt:

        # CSRF-token
        "with_csrftoken"False,
        # voorvoegsel van de URL van de applicatie
        # stel de tekenreeks in op leeg als je geen prefix wilt, of anders /prefix
        "prefix_url""/do",
        # hoofd-URL van de Apache-server – laat de tekenreeks leeg voor uitvoering buiten Apache
        "application_root""/impots"

We starten de Apache-server en de twee SGBD-processen. We vragen de URL en [https://flask-impots-withmysql/impots/do] op. Het antwoord van de server is als volgt:

Image

We krijgen nu wel het authenticatiescherm te zien dat we in de vorige versie niet konden openen. De rest van de applicatie werkt normaal.

Nu testen we de andere virtuele server. We vragen de URL en [https://flask-impots-withpgres/impots/do] op. Het antwoord van de server is als volgt:

Image

De begrippen 'alias' (WSGI) en 'voorvoegsel' (URL) vervullen dezelfde functie. Een van deze twee begrippen is overbodig. Om de URL van de Apache-server te voorzien van het voorvoegsel [/impots/do], zijn er dus drie manieren:

1 – [WGSIAlias /impots] en [prefix_url=’/do’];

2 – [WGSIAlias /] en [prefix_url=’/impots/do’];

3 – [WGSIAlias /impots/do] en [prefix_url=’’];

38.2. Consoletests

We gebruiken opnieuw de consoletests van de client [http-clients/09]:

Image

  • de URL van de server moet worden aangepast in de configuraties [1] en [3];
  • er moet een wijziging worden aangebracht in de laag [dao] zodat deze het protocol HTTPS van de Apache-server ondersteunt;

In de bestanden [config] wordt de URL van de server als volgt gewijzigd:


        "server": {
            # "urlServer": "http://127.0.0.1:5000",
            # "urlServer": "http://127.0.0.1:5000/do",
            "urlServer""https://flask-impots-withmysql/impots/do",
            "user": {
                "login""admin",
                "password""admin"
            },
            "url_services": {
                
            }
        },
        # debugmodus
        "debug"True,
        # csrf_token
        "with_csrftoken"False,
  • regel 4: de nieuwe URL van de server. Voor de eerste keer in dit document gebruikt de client het protocol HTTPS;

De klasse [ImpôtsDaoWihHttpSession] van de laag [dao] verandert als volgt:


…    
     # verzoek-/antwoordfase
    def get_response(self, method: str, url_service: str, data_value: dict = None, json_value=None):
        # [method]: methode HTTP GET of POST
        # [url_service]: URL-service
        # [data]: parameters van POST in x-www-form-urlencoded
        # [json]: parameters van POST in JSON
        # [cookies]: cookies die in het verzoek moeten worden opgenomen

        # er moet een sessie zijn met XML of JSON, anders kan het antwoord niet worden verwerkt
        if self.__session_type not in ['json''xml']:
            raise ImpôtsError(73"il n'y a pas de session valide en cours")

        # het token CSRF wordt toegevoegd aan de servicetoken URL
        if self.__csrf_token:
            url_service = f"{url_service}/{self.__csrf_token}"

        # het verzoek wordt uitgevoerd
        response = requests.request(method,
                                    url_service,
                                    data=data_value,
                                    json=json_value,
                                    cookies=self.__cookies,
                                    allow_redirects=True,
                                    # voor het https-protocol
                                    verify=False)

        # debugmodus?
        if self.__debug:
            # inlogger
            if not self.__logger:
                self.__logger = self.__config['logger']
            # inloggen
            self.__logger.write(f"{response.text}\n")

        

        # het resultaat wordt weergegeven
        return résultat['réponse']
  • op regel 26 wordt de parameter [verify=False] toegevoegd vanwege het protocol HTTPS dat door de Apache-server wordt gebruikt. De module [requests] (regel 19) ondersteunt het protocol HTTPS standaard. Standaard controleert deze module de geldigheid van het beveiligingscertificaat dat de server HTTPS naar hem verstuurt en genereert hij een uitzondering als het ontvangen certificaat ongeldig is. Dit is hier het geval, aangezien de Apache-server van Laragon een zelfondertekend certificaat verstuurt. Om de uitzondering te voorkomen, gebruiken we de parameter [verify=False] om de module [requests] te vertellen geen uitzondering te genereren. [requests] geeft dan alleen een waarschuwing (warning) weer op de console.

Nadat deze wijzigingen zijn doorgevoerd, zouden alle consoletests moeten werken.