Packages
plug
1.13.3
1.20.3
1.20.2
1.20.1
retired
1.20.0
retired
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.5
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
1.16.1
1.16.0
1.15.6
1.15.5
1.15.4
1.15.3
1.15.2
1.15.1
1.15.0
1.14.2
1.14.1
1.14.0
1.13.6
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
retired
1.13.0
retired
1.12.1
1.12.0
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.5.0-rc.2
1.5.0-rc.1
1.5.0-rc.0
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.0
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.2.0-rc.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.14.0
0.13.1
0.13.0
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.3
0.5.2
0.5.1
0.5.0
0.4.4
0.4.3
0.4.2
0.4.1
Compose web applications with functions
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/plug/session.ex
defmodule Plug.Session do
@moduledoc """
A plug to handle session cookies and session stores.
The session is accessed via functions on `Plug.Conn`. Cookies and
session have to be fetched with `Plug.Conn.fetch_session/1` before the
session can be accessed.
The session is also lazy. Once configured, a cookie header with the
session will only be sent to the client if something is written to the
session in the first place.
When using `Plug.Session`, also consider using `Plug.CSRFProtection`
to avoid Cross Site Request Forgery attacks.
## Session stores
See `Plug.Session.Store` for the specification session stores are required to
implement.
Plug ships with the following session stores:
* `Plug.Session.ETS`
* `Plug.Session.COOKIE`
## Options
* `:store` - session store module (required);
* `:key` - session cookie key (required);
* `:domain` - see `Plug.Conn.put_resp_cookie/4`;
* `:max_age` - see `Plug.Conn.put_resp_cookie/4`;
* `:path` - see `Plug.Conn.put_resp_cookie/4`;
* `:secure` - see `Plug.Conn.put_resp_cookie/4`;
* `:http_only` - see `Plug.Conn.put_resp_cookie/4`;
* `:same_site` - see `Plug.Conn.put_resp_cookie/4`;
* `:extra` - see `Plug.Conn.put_resp_cookie/4`;
Additional options can be given to the session store, see the store's
documentation for the options it accepts.
## Examples
plug Plug.Session, store: :ets, key: "_my_app_session", table: :session
"""
alias Plug.Conn
@behaviour Plug
@cookie_opts [:domain, :max_age, :path, :secure, :http_only, :extra, :same_site]
@impl true
def init(opts) do
store = Plug.Session.Store.get(Keyword.fetch!(opts, :store))
key = Keyword.fetch!(opts, :key)
cookie_opts = Keyword.take(opts, @cookie_opts)
store_opts = Keyword.drop(opts, [:store, :key] ++ @cookie_opts)
store_config = store.init(store_opts)
%{
store: store,
store_config: store_config,
key: key,
cookie_opts: cookie_opts
}
end
@impl true
def call(conn, config) do
Conn.put_private(conn, :plug_session_fetch, fetch_session(config))
end
defp fetch_session(config) do
%{store: store, store_config: store_config, key: key} = config
fn conn ->
{sid, session} =
if cookie = conn.cookies[key] do
store.get(conn, cookie, store_config)
else
{nil, %{}}
end
session = Map.merge(session, Map.get(conn.private, :plug_session, %{}))
conn
|> Conn.put_private(:plug_session, session)
|> Conn.put_private(:plug_session_fetch, :done)
|> Conn.register_before_send(before_send(sid, config))
end
end
defp before_send(sid, config) do
fn conn ->
case Map.get(conn.private, :plug_session_info) do
:write ->
value = put_session(sid, conn, config)
put_cookie(value, conn, config)
:drop ->
drop_session(sid, conn, config)
:renew ->
renew_session(sid, conn, config)
:ignore ->
conn
nil ->
conn
end
end
end
defp drop_session(sid, conn, config) do
if sid do
delete_session(sid, conn, config)
delete_cookie(conn, config)
else
conn
end
end
defp renew_session(sid, conn, config) do
if sid, do: delete_session(sid, conn, config)
value = put_session(nil, conn, config)
put_cookie(value, conn, config)
end
defp put_session(sid, conn, %{store: store, store_config: store_config}),
do: store.put(conn, sid, conn.private[:plug_session], store_config)
defp delete_session(sid, conn, %{store: store, store_config: store_config}),
do: store.delete(conn, sid, store_config)
defp put_cookie(value, conn, %{cookie_opts: cookie_opts, key: key}),
do: Conn.put_resp_cookie(conn, key, value, cookie_opts)
defp delete_cookie(conn, %{cookie_opts: cookie_opts, key: key}),
do: Conn.delete_resp_cookie(conn, key, cookie_opts)
end