Explorar o código

Support cookie based auth

Gilbert Wong %!s(int64=6) %!d(string=hai) anos
pai
achega
81ef5b9b8d
Modificáronse 3 ficheiros con 23 adicións e 5 borrados
  1. 10 4
      src/emqx_protocol.erl
  2. 12 0
      src/emqx_ws_connection.erl
  3. 1 1
      test/rfc6455_client.erl

+ 10 - 4
src/emqx_protocol.erl

@@ -68,7 +68,8 @@
           ignore_loop,
           topic_alias_maximum,
           conn_mod,
-          credentials
+          credentials,
+          ws_cookie
         }).
 
 -opaque(state() :: #pstate{}).
@@ -85,7 +86,9 @@
 %%------------------------------------------------------------------------------
 
 -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),
     #pstate{zone                = Zone,
             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),
             topic_alias_maximum = #{to_client => 0, from_client => 0},
             conn_mod            = maps:get(conn_mod, SocketOpts, undefined),
-            credentials         = #{}}.
+            credentials         = #{},
+            ws_cookie           = maps:get(ws_cookie, SocketOpts, undefined)}.
 
 init_username(Peercert, Options) ->
     case proplists:get_value(peer_cert_as_username, Options) of
@@ -202,11 +206,13 @@ credentials(#pstate{zone      = Zone,
                     client_id = ClientId,
                     username  = Username,
                     peername  = Peername,
-                    peercert  = Peercert}) ->
+                    peercert  = Peercert,
+                    ws_cookie = WsCookie}) ->
     with_cert(#{zone => Zone,
                 client_id => ClientId,
                 username => Username,
                 peername => Peername,
+                ws_cookie => WsCookie,
                 mountpoint => emqx_zone:get_env(Zone, mountpoint)}, Peercert).
 
 with_cert(Credentials, undefined) -> Credentials;

+ 12 - 0
src/emqx_ws_connection.erl

@@ -138,10 +138,22 @@ websocket_init(#state{request = Req, options = Options}) ->
     Peername = cowboy_req:peer(Req),
     Sockname = cowboy_req:sock(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,
                                       sockname => Sockname,
                                       peercert => Peercert,
                                       sendfun  => send_fun(self()),
+                                      ws_cookie => WsCookie,
                                       conn_mod => ?MODULE}, Options),
     ParserState = emqx_protocol:parser(ProtoState),
     Zone = proplists:get_value(zone, Options),

+ 1 - 1
test/rfc6455_client.erl

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