/ds_web/src/ds_web_session.erl

http://github.com/Licenser/dividedspace · Erlang · 95 lines · 37 code · 18 blank · 40 comment · 0 complexity · 9c625766592512f019fab0e0a7effff1 MD5 · raw file

  1. %%%-------------------------------------------------------------------
  2. %%% @author Heinz N. Gies <heinz@licenser.net>
  3. %%% @copyright (C) 2011, Heinz N. Gies
  4. %%% @doc This module provides simple Session handling with the data
  5. %%% entirely stored in the cookie, aka on the client. The data
  6. %%% is encrypted using an AES 128 CBC encryption to prevent
  7. %%% tempering.
  8. %%% Any Erlang term can be used as Session data.
  9. %%%
  10. %%% @end
  11. %%% Created : 9 Dec 2011 by Heinz N. Gies <heinz@licenser.net>
  12. %%%-------------------------------------------------------------------
  13. -module(ds_web_session).
  14. %% API
  15. -export([get/1, set/2, get_session/3, set_session/4, rem_session/2]).
  16. %%%===================================================================
  17. %%% API
  18. %%%===================================================================
  19. get(Req) ->
  20. {ok, SessionCookieName} = application:get_env(ds_web, session_name),
  21. {ok, SessionKey} = application:get_env(ds_web, session_key),
  22. get_session(SessionCookieName, SessionKey, Req).
  23. set(Req, Session) ->
  24. {ok, SessionCookieName} = application:get_env(ds_web, session_name),
  25. {ok, SessionKey} = application:get_env(ds_web, session_key),
  26. set_session(SessionCookieName, SessionKey, Req, Session).
  27. %%--------------------------------------------------------------------
  28. %% @doc Retrieves the session data from the cookies, returns either a
  29. %% the term stored or undefined when no session was found.
  30. %% SessionKey needs to be of the size 16 or a multiplyer from it.
  31. %% @spec get_session(binary(), binary(), #http_req{})
  32. %% -> undefined | term()
  33. %% @end
  34. %%--------------------------------------------------------------------
  35. get_session(SessionCookieName, SessionKey, Req) ->
  36. case cowboy_http_req:cookie(SessionCookieName,Req) of
  37. {undefined, _Req} ->
  38. undefined;
  39. {<<>>, _Req} ->
  40. undefined;
  41. {SessionData, _Req} ->
  42. dec_term(SessionKey, SessionData)
  43. end.
  44. %%--------------------------------------------------------------------
  45. %% @doc Sets the session data as a cookie in the Request.
  46. %% SessionKey needs to be of the size 16 or a multiplyer from it.
  47. %% @spec set_session(binary(), binary(), #http_req{}, term())
  48. %% -> {ok, #http_req{}}
  49. %% @end
  50. %%--------------------------------------------------------------------
  51. set_session(SessionCookieName, SessionKey, Req, Session) ->
  52. cowboy_http_req:set_resp_cookie(SessionCookieName, enc_term(SessionKey, Session), [{max_age, 365*24*3600}], Req).
  53. %%--------------------------------------------------------------------
  54. %% @doc Deletes the session data as a cookie in the Request.
  55. %% @spec rem_session(binary(), binary(), #http_req{}, term())
  56. %% -> {ok, #http_req{}}
  57. %% @end
  58. %%--------------------------------------------------------------------
  59. rem_session(SessionCookieName, Req) ->
  60. cowboy_http_req:set_resp_cookie(SessionCookieName, <<>>, [{max_age, 0}], Req).
  61. %%%===================================================================
  62. %%% Internal functions
  63. %%%===================================================================
  64. aes_dec(Key, Text) when is_binary(Text) ->
  65. <<Size:32, IVec:16/binary, Messag/binary>> = Text,
  66. <<Msg:Size/binary, _/binary>> = crypto:aes_cbc_128_decrypt(Key, IVec, Messag),
  67. Msg.
  68. aes_enc(Key, Text) when is_binary(Text) ->
  69. MsgSize = size(Text),
  70. Missing = (16 - (MsgSize rem 16)) * 8,
  71. IVec = crypto:aes_cbc_ivec(crypto:rand_bytes(16)),
  72. Enc = crypto:aes_cbc_128_encrypt(Key, IVec, <<Text/binary, 0:Missing>>),
  73. <<MsgSize:32, IVec:16/binary, Enc/binary>>.
  74. enc_term(Key, Term) when is_binary(Key)->
  75. list_to_binary(edoc_lib:escape_uri(binary_to_list(base64:encode(aes_enc(Key, term_to_binary(Term)))))).
  76. dec_term(Key, Term) when is_binary(Term), is_binary(Key) ->
  77. binary_to_term(aes_dec(Key, base64:decode(cowboy_http:urldecode(Term)))).