2016-08-03 3 views
1

Ich habe Funktionen in meinem API-Code, von denen einige nur angeforderte Ergebnisse nur an diejenigen Anfragen zurückgeben sollten, die ein korrektes Token haben. Wenn die Anfrage nicht autorisiert ist, geben Sie eine generische 401-Antwort zurück.Wie können einige API-Funktionen nur für autorisierte Benutzer in Erlang verfügbar gemacht werden?

Ich habe eine Hilfsfunktion is_authorised() erstellt, die wahr/falsch zurückgibt.

Nun, in einer Funktion, die ich nur autorisierten Benutzern zugänglich machen möchte, überprüfe ich das Ergebnis der is_authorised() Funktion und gebe die entsprechende Antwort zurück. Hier

ein Beispiel:

get_players(SessionID, _Env, _Input) -> 
    case is_authorized(_Env) of 
     true -> 
      Response = [json_header(), players:select_all()]; 
     false -> 
      Response = get_unauthorized_response() 
    end, 
    mod_esi:deliver(SessionID, Response). 

Ich frage mich, ob es möglich ist, um diese Überprüfung eleganter aussehen zu lassen, wie Python Dekorateure in Flask verwendet.

@app.route('/user') 
@required_roles('admin', 'user') 
def user_page(self): 
    return "You've got permission to access this page." 

Ich weiß, dass ich benutzerdefinierte Funktionen in Wachen nicht verwenden kann, also denke ich, dass es nicht möglich ist, es als Wache zu machen.

Bitte beraten.

Antwort

2

Nicht so elegant wie Python Dekoratoren, aber Sie können Funktionen höherer Ordnung verwenden, um dies viel sauberer zu machen. Erstellen Sie eine Funktion, die SessionID, Env, Input und eine Callback-Funktion akzeptiert, die ausgeführt werden soll, wenn der Benutzer berechtigt ist, und rufen Sie diese Funktion aus allen Funktionen auf, die die Berechtigungsprüfung durchführen müssen.

(ungetestet) Code:

authorized(SessionID, Env, Input, Fun) -> 
    Response = case is_authorized(Env) of 
     true -> 
      Fun(); 
     false -> 
      get_unauthorized_response() 
    end, 
    mod_esi:deliver(SessionID, Response). 

get_players(SessionID, Env, Input) -> 
    authorized(SessionID, Env, Input, fun() -> 
     [json_header(), players:select_all()] 
    end). 

Sie können mehr Argumente authorized geben, wenn Sie weitergehende Kontrollen tun möchten. Mit einer role_of/1 Funktion, die Env und gibt die Rolle als ein Atom annimmt, können Sie den Zugriff auf bestimmte Benutzer mit so etwas wie dies ermöglichen:

authorized(SessionID, Env, Input, Roles, Fun) -> 
    Response = case lists:member(role_of(Env), Roles) of 
     true -> 
      Fun(); 
     false -> 
      get_unauthorized_response() 
    end, 
    mod_esi:deliver(SessionID, Response). 

get_players(SessionID, Env, Input) -> 
    authorized(SessionID, Env, Input, [admin, user], fun() -> 
     [json_header(), players:select_all()] 
    end). 
+0

Ich dachte auch über diesen Ansatz nach, scheint, dass ich verwenden werde, sieht gut aus, danke! –

+0

@SergeiBasharov siehe auch meine Bearbeitung. Auf diese Weise können Sie wahrscheinlich das Verhalten dieses Python-Snippets emulieren. – Dogbert

0

Sie könnten in Cowboy oder webmachine aussehen wollen, wie sie Ihnen geben würde eine Framework über eine Zustandsmaschine zum Behandeln von REST-Anforderungen. Implementieren Sie den Rückruf "Verboten/2", um auf nicht autorisierten Zugriff hinzuweisen.

Nebenbei bemerkt: Ein 401-Statuscode zeigt einen Fehler der Authentifizierung auf der http-Ebene, wenn einer der bekannten http-Authentifizierungsmechanismen wie basic ausgeführt wird. Siehe auch https://en.wikipedia.org/wiki/Basic_access_authentication Sie haben es mit einem Autorisierungsfehler zu tun und der korrekte zugehörige http-Statuscode für diesen Fall wäre 403 (wie der verbotene Rückruf von oben zurückkehren würde).