rabbitmq基於http的認證和授權
阿新 • • 發佈:2019-01-05
關於使用者的登入。
user_login_authentication(Username, AuthProps) -> case http_req(p(user_path), q([{username, Username}|AuthProps])) of {error, _} = E -> E; deny -> {refused, "Denied by HTTP plugin", []}; "allow" ++ Rest -> Tags = [list_to_atom(T) || T <- string:tokens(Rest, " ")], {ok, #auth_user{username = Username, tags = Tags, impl = none}}; Other -> {error, {bad_response, Other}} end. q(Args) -> string:join([escape(K, V) || {K, V} <- Args], "&"). escape(K, Map) when is_map(Map) -> string:join([escape(rabbit_data_coercion:to_list(K) ++ "." ++ rabbit_data_coercion:to_list(Key), Value) || {Key, Value} <- maps:to_list(Map)], "&"); escape(K, V) -> rabbit_data_coercion:to_list(K) ++ "=" ++ rabbit_http_util:quote_plus(V).
首先,所有的引數都會通過q()方法強行被組裝成url中get方法引數連結的形式,類似username=username&password=password的字串,便於在後面的請求中便於裝配。
之後根據p()得到配置中的rabbitmq_auth_backend_http引數,也就是目標驗證服務的地址。
p(PathName) ->
{ok, Path} = application:get_env(rabbitmq_auth_backend_http, PathName),
Path.
在得到了以上引數之後,也就是服務目標地址與驗證所需要的引數,通過http_req方法呼叫,準備開始傳送
http_req(Path, Query) -> http_req(Path, Query, ?RETRY_ON_KEEPALIVE_CLOSED). http_req(Path, Query, Retry) -> case do_http_req(Path, Query) of {error, socket_closed_remotely} -> %% HTTP keepalive connection can no longer be used. Retry the request. case Retry > 0 of true -> http_req(Path, Query, Retry - 1); false -> {error, socket_closed_remotely} end; Other -> Other end. do_http_req(PathName, Query) -> URI = uri_parser:parse(PathName, [{port, 80}]), {host, Host} = lists:keyfind(host, 1, URI), {port, Port} = lists:keyfind(port, 1, URI), HostHdr = rabbit_misc:format("~s:~b", [Host, Port]), {ok, Method} = application:get_env(rabbitmq_auth_backend_http, http_method), Request = case rabbit_data_coercion:to_atom(Method) of get -> {PathName ++ "?" ++ Query, [{"Host", HostHdr}]}; post -> {PathName, [{"Host", HostHdr}], "application/x-www-form-urlencoded", Query} end, HttpOpts = case application:get_env(rabbitmq_auth_backend_http, ssl_options) of {ok, Opts} when is_list(Opts) -> [{ssl, Opts}]; _ -> [] end, case httpc:request(Method, Request, HttpOpts, []) of {ok, {{_HTTP, Code, _}, _Headers, Body}} -> case Code of 200 -> case parse_resp(Body) of {error, _} = E -> E; Resp -> Resp end; _ -> {error, {Code, Body}} end; {error, _} = E -> E end.
在do_http_req()方法,首先根據之前得到的目標驗證服務地址解析相應的 主機名和埠號(預設埠號80)。在從rabbitmq的配置檔案中讀取rabbitmq_auth_backend_http裡的http_method引數,以此來確定驗證所需要的方法(只支援get或者post方法),並再次讀取配置中ssl_opts作為訪問時需要的證書,。
之後組裝為request直接傳送請求至相應的認證服務。
如果連線失敗,也會在相應的重試次數下繼續嘗試連線。
在獲得response之後並確認成功之後,對於使用者登入的認證之外,還可以接收除了allow之後,可以在之後空格之後加角色,會解析成tags一併返回,而除了allow之外的所有請求都會被視為拒絕。
以上是使用者的登入的驗證。
其他的關於資源的許可權授權也與以上大同小異。