一、工作环境准备
准备好redis server,http://blog.csdn.net/libaineu2004/article/details/76267836
erlang redis客户端使用开源项目,https://github.com/wooga/eredis
erlang连接池,https://github.com/emqtt/ecpool
emq使用的是v2.3.5版本,https://github.com/emqtt/emq-relx
我们以插件emq_auth_redis来实现,路径是/home/firecat/Prj/emq2.0/emq-relx-2.3.5/deps/emq_auth_redis
/home/firecat/Prj/emq2.0/emq-relx-2.3.5/data/loaded_plugins设置自启动插件
emq_recon. emq_modules. emq_retainer. emq_dashboard. emq_auth_redis.
二、redis数据准备
对照/home/firecat/Prj/emq2.0/emq-relx-2.3.5/deps/emq_auth_redis/README.md说明文档,往redis数据库写入username和password:
格式
HSET mqtt_user:<username> password "password"
命令
[root@localhost src]# ./redis-cli 127.0.0.1:6379> HSET mqtt_user:firecat password "123456" (integer) 1 127.0.0.1:6379> HSET mqtt_user:lqh password "pass123" (integer) 1 127.0.0.1:6379> HSET mqtt_user:firecatGTerm password "he2345v11t11" (integer) 1 127.0.0.1:6379> hgetall mqtt_user (empty list or set) 127.0.0.1:6379> HMGET mqtt_user:lqh password 1) "pass123" 127.0.0.1:6379> hgetall mqtt_user:lqh 1) "password" 2) "pass123"
源文件/home/firecat/Prj/emq2.0/emq-relx-2.3.5/deps/emqttd/src/emqttd_access_control.erl会启用校验
%% @doc Authenticate MQTT Client. -spec(auth(Client :: mqtt_client(), Password :: password()) -> ok | {ok, boolean()} | {error, term()}). auth(Client, Password) when is_record(Client, mqtt_client) -> auth(Client, Password, lookup_mods(auth)). auth(_Client, _Password, []) -> case emqttd:env(allow_anonymous, false) of true -> ok; false -> {error, "No auth module to check!"} end; auth(Client, Password, [{Mod, State, _Seq} | Mods]) -> case catch Mod:check(Client, Password, State) of ok -> ok; {ok, IsSuper} -> {ok, IsSuper}; ignore -> auth(Client, Password, Mods); {error, Reason} -> {error, Reason}; {'EXIT', Error} -> {error, Error} end.
源文件emq_auth_redis.erl,有校验的实施过程
check(Client, Password, #state{auth_cmd = AuthCmd,
super_cmd = SuperCmd,
hash_type = HashType}) ->
Result = case emq_auth_redis_cli:q(AuthCmd, Client) of
源文件emq_auth_redis_cli.erl,有redis的查询命令实现方法
%% Redis Query.
-spec(q(string(), mqtt_client()) -> {ok, undefined | binary() | list()} | {error, atom() | binary()}).
q(CmdStr, Client) ->
io:format("1 CmdStr is: ~s ~n", [CmdStr]),
Cmd = string:tokens(replvar(CmdStr, Client), " "),
io:format("2 Cms is: ~s ~n", [Cmd]),
ecpool:with_client(?APP, fun(C) -> eredis:q(C, Cmd) end).
ereids的使用案例,https://github.com/wooga/eredis
{ok, C} = eredis:start_link().
{ok, <<"OK">>} = eredis:q(C, ["SET", "foo", "bar"]).
{ok, <<"bar">>} = eredis:q(C, ["GET", "foo"]).
KeyValuePairs = ["key1", "value1", "key2", "value2", "key3", "value3"].
{ok, <<"OK">>} = eredis:q(C, ["MSET" | KeyValuePairs]).
{ok, Values} = eredis:q(C, ["MGET" | ["key1", "key2", "key3"]]).
string:tokens的用法可以参考erlang官方文档,http://erlang.org/doc/man/string.html
tokens(String, SeparatorList) -> Tokens
Types
String = SeparatorList = string()
Tokens = [Token :: nonempty_string()]
Returns a list of tokens in String, separated by the characters in SeparatorList.
Example:
> tokens("abc defxxghix jkl", "x ").
["abc", "def", "ghi", "jkl"]
三、除了emq_auth_redis_cli.erl上诉的查询方法,我们自己也可以实现其他查询方法:
-export([connect/1, q/2, q2/2]). %% Redis Query.firecat add. -spec(q2(string(), binary()) -> {ok, undefined | binary() | list()} | {error, atom() | binary()}). q2(CmdStr, ClientId) -> io:format("3 CmdStr is: ~s ~n", [CmdStr]), Cmd = string:tokens(replvar(CmdStr, "%c", ClientId), " "), io:format("4 Cms is: ~s ~n", [Cmd]), ecpool:with_client(?APP, fun(C) -> eredis:q(C, Cmd) end).
这样,我在其他任意的erlang mod,都可以调用该方法,例如**.erl:
%%%% redis test redis_test(ClientId) -> Result = case emq_auth_redis_cli:q2("HMGET mqtt_clientid:%c user group type", ClientId) of {ok, [undefined|_]} -> io:format("clientid ignore: undefined ~n"), %%firecat {error, undefined}; {ok, [User, Group, Type]} -> %%[undefined, undefined, undefined] io:format("clientid is: ~s ~s ~s ~n", [User, Group, Type]), ok; {error, Reason} -> io:format("clientid error is: ~s ~n", [Reason]), {error, Reason} end, case Result of ok -> ok; %%firecat Error -> ok end.
四、redis插件除了可以检验username和password,还可以校验clientid的合法性。需要手动新增源文件emq_clientid_redis.erl。完整的源码请访问:
https://download.csdn.net/download/libaineu2004/10289890