2017-01-29 2 views
2

Ich arbeite an einer Vanille Elixir/Phoenix-Anwendung und folgte den allgemeinen Schritten in Programming Phoenix Buch, um ein Basiszeichen in & Sign-out-System zu implementieren (siehe Schnipsel unten). Ich sehe jedoch keinen Rat in dem Buch oder online darüber, wie Cookie-basierte Plug-Sitzungen nach einer gewissen Zeit ablaufen. Was sind einige Ansätze für das Timeout von Sitzungen in Phoenix-Apps?Elixir/Phoenix: So implementieren Sie Session Timeout/Ablauf

Hier einige relevante Schnipsel meines nackten Knochen Auth-System:

In endpoint.ex wird die App konfiguriert, um eine Nur-Lese-Session-Cookie-basierte zu verwenden:

plug Plug.Session, 
    store: :cookie, 
    key: "_zb_key", 
    signing_salt: "RANDOM HEX" 

ich einen Stecker schrieb auth.ex die (unter anderem) in einem authentifizierten Benutzer anmelden, und current_user basierend auf der Sitzung user_id in nachfolgenden Anfragen gefunden einstellen:

def login!(conn, user) do 
    conn 
    |> assign(:current_user, user) 
    |> put_session(:user_id, user.id) 
    |> configure_session(renew: true) 
end 

# ... more ... 

def load_current_user(conn, _opts) do 
    cond do 
    conn.assigns[:current_user] -> 
     conn # If :current_user was already set, honor it 
    user_id = get_session(conn, :user_id) -> 
     user = Zb.Repo.get!(Zb.User, user_id) 
     assign(conn, :current_user, user) 
    true -> 
     conn # No user_id was found; make no changes 
    end 
end 

# ... more ... 

Antwort

2

Zuerst suchte ich nach Cookie-Verfallsoptionen in the Plug library, erkannte dann, dass ein einfacher (und sicherer) Ansatz einfach ist, ein Ablaufdatum in der Sitzung zusammen mit der Benutzer-ID festzulegen. Die Sitzung ist manipulationssicher. Wenn ich also jede Anfrage erhalte, kann ich die Datetime mit Now vergleichen; Wenn die Sitzung noch nicht abgelaufen ist, setze ich current_user als normal. Ansonsten rufe ich logout! an, um die abgelaufene Sitzung zu löschen.

Eine Implementierung in etwa so aussehen würde (erfordert die Timex Bibliothek):

# Assign current_user to the conn, if a user is logged in 
def load_current_user(conn, _opts) do 
    cond do 
    no_login_session?(conn) -> 
     conn # No user_id was found; make no changes 
    current_user_already_set?(conn) -> 
     conn 
    session_expired?(conn) -> 
     logout!(conn) 
    user = load_user_from_session(conn) -> 
     conn 
     |> put_session(:expires_at, new_expiration_datetime_string) 
     |> assign(:current_user, user) 
    end 
end 

defp session_expired?(conn) do 
    expires_at = get_session(conn, :expires_at) |> Timex.parse!("{ISO:Extended}") 
    Timex.after?(Timex.now, expires_at) 
end 

# ... more ... 

# Start a logged-in session for an (already authenticated) user 
def login!(conn, user) do 
    conn 
    |> assign(:current_user, user) 
    |> put_session(:user_id, user.id) 
    |> put_session(:expires_at, new_expiration_datetime_string) 
    |> configure_session(renew: true) 
end 

defp new_expiration_datetime_string do 
    Timex.now |> Timex.shift(hours: +2) |> Timex.format("{ISO:Extended}") 
end 

# ... more ... 
Verwandte Themen