Support cookie based auth

This commit is contained in:
Gilbert Wong 2019-04-10 18:50:28 +08:00 committed by Gilbert
parent 4d2bc48822
commit 81ef5b9b8d
3 changed files with 23 additions and 5 deletions

View File

@ -68,7 +68,8 @@
ignore_loop, ignore_loop,
topic_alias_maximum, topic_alias_maximum,
conn_mod, conn_mod,
credentials credentials,
ws_cookie
}). }).
-opaque(state() :: #pstate{}). -opaque(state() :: #pstate{}).
@ -85,7 +86,9 @@
%%------------------------------------------------------------------------------ %%------------------------------------------------------------------------------
-spec(init(map(), list()) -> state()). -spec(init(map(), list()) -> state()).
init(SocketOpts = #{peername := Peername, peercert := Peercert, sendfun := SendFun}, Options) -> init(SocketOpts = #{ peername := Peername
, peercert := Peercert
, sendfun := SendFun}, Options) ->
Zone = proplists:get_value(zone, Options), Zone = proplists:get_value(zone, Options),
#pstate{zone = Zone, #pstate{zone = Zone,
sendfun = SendFun, sendfun = SendFun,
@ -110,7 +113,8 @@ init(SocketOpts = #{peername := Peername, peercert := Peercert, sendfun := SendF
ignore_loop = emqx_config:get_env(mqtt_ignore_loop_deliver, false), ignore_loop = emqx_config:get_env(mqtt_ignore_loop_deliver, false),
topic_alias_maximum = #{to_client => 0, from_client => 0}, topic_alias_maximum = #{to_client => 0, from_client => 0},
conn_mod = maps:get(conn_mod, SocketOpts, undefined), conn_mod = maps:get(conn_mod, SocketOpts, undefined),
credentials = #{}}. credentials = #{},
ws_cookie = maps:get(ws_cookie, SocketOpts, undefined)}.
init_username(Peercert, Options) -> init_username(Peercert, Options) ->
case proplists:get_value(peer_cert_as_username, Options) of case proplists:get_value(peer_cert_as_username, Options) of
@ -202,11 +206,13 @@ credentials(#pstate{zone = Zone,
client_id = ClientId, client_id = ClientId,
username = Username, username = Username,
peername = Peername, peername = Peername,
peercert = Peercert}) -> peercert = Peercert,
ws_cookie = WsCookie}) ->
with_cert(#{zone => Zone, with_cert(#{zone => Zone,
client_id => ClientId, client_id => ClientId,
username => Username, username => Username,
peername => Peername, peername => Peername,
ws_cookie => WsCookie,
mountpoint => emqx_zone:get_env(Zone, mountpoint)}, Peercert). mountpoint => emqx_zone:get_env(Zone, mountpoint)}, Peercert).
with_cert(Credentials, undefined) -> Credentials; with_cert(Credentials, undefined) -> Credentials;

View File

@ -138,10 +138,22 @@ websocket_init(#state{request = Req, options = Options}) ->
Peername = cowboy_req:peer(Req), Peername = cowboy_req:peer(Req),
Sockname = cowboy_req:sock(Req), Sockname = cowboy_req:sock(Req),
Peercert = cowboy_req:cert(Req), Peercert = cowboy_req:cert(Req),
WsCookie = try cowboy_req:parse_cookies(Req)
catch
error:badarg ->
?LOG(error, "[WS Connection] Illegal cookie"),
undefined;
Error:Reason ->
?LOG(error,
"[WS Connection] Cookie is parsed failed, Error: ~p, Reason ~p",
[Error, Reason]),
undefined
end,
ProtoState = emqx_protocol:init(#{peername => Peername, ProtoState = emqx_protocol:init(#{peername => Peername,
sockname => Sockname, sockname => Sockname,
peercert => Peercert, peercert => Peercert,
sendfun => send_fun(self()), sendfun => send_fun(self()),
ws_cookie => WsCookie,
conn_mod => ?MODULE}, Options), conn_mod => ?MODULE}, Options),
ParserState = emqx_protocol:parser(ProtoState), ParserState = emqx_protocol:parser(ProtoState),
Zone = proplists:get_value(zone, Options), Zone = proplists:get_value(zone, Options),

View File

@ -36,7 +36,7 @@ new(WsUrl, PPid) ->
addr = Addr, addr = Addr,
path = "/" ++ Path, path = "/" ++ Path,
ppid = PPid}, ppid = PPid},
spawn(fun () -> spawn(fun() ->
start_conn(State) start_conn(State)
end). end).