【发布时间】:2016-01-21 10:43:58
【问题描述】:
如何从phoenixframework中的socket获取remote_ip?我可以从 View 中的 conn 获取它,但不能在 Channel 中获取。
非常感谢您的帮助!
【问题讨论】:
标签: sockets ip elixir phoenix-framework
如何从phoenixframework中的socket获取remote_ip?我可以从 View 中的 conn 获取它,但不能在 Channel 中获取。
非常感谢您的帮助!
【问题讨论】:
标签: sockets ip elixir phoenix-framework
现在的答案是:你不能。您无法访问通道中的连接,因为通道与传输无关。在 Phoenix 中打开一个问题,详细说明您的用户案例,以便 Phoenix 团队可以采取行动。
【讨论】:
此处提供的答案副本:https://elixirforum.com/t/phoenix-socket-channels-security-ip-identification/1463/3(所有功劳归于https://elixirforum.com/u/arjan)
凤凰 1.4 更新:
从 Phoenix 1.4 开始,您可以从底层传输中获取连接信息。您获得的信息类型取决于传输,但使用 WebSocket 传输可以检索对等信息(IP 地址)和 x-headers 列表(用于 x-forwarded-for 解析)。
在您的 endpoint.ex 中像这样配置您的套接字:
socket("/socket", MyApp.Web.UserSocket,
websocket: [connect_info: [:peer_data, :x_headers]],
longpoll: [connect_info: [:peer_data, :x_headers]]
)
然后你的 UserSocket 模块必须像这样公开一个 connect/3 函数:
def connect(_params, socket, connect_info) do
{:ok, socket}
end
在连接时,connect_info 参数现在包含来自传输的信息:
info: %{
peer_data: %{address: {127, 0, 0, 1}, port: 52372, ssl_cert: nil},
x_headers: []
}
更新
如果您的 Phoenix 应用程序没有直接处理流量,而是从反向代理(如 nginx)接收流量,那么 peer_data 将拥有 nginx IP 地址,而不是客户端的 IP 地址。
要解决此问题,您可以告诉 nginx(或您使用的任何代理)在标头中传递原始 IP,然后稍后再阅读。
所以你的凤凰位置应该是这样的:
location /phoenix/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://phoenix/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
你的套接字代码应该有这个:
defp get_ip_address(%{x_headers: headers_list}) do
header = Enum.find(headers_list, fn {key, _val} -> key == "x-real-ip" end)
case header do
nil ->
nil
{_key, value} ->
value
_ ->
nil
end
end
defp get_ip_address(_) do
nil
end
并将连接更改为类似的东西
def connect(params, socket, connect_info) do
socket = assign(socket, :ip_address, get_ip_address(connect_info))
{:ok, socket}
end
【讨论】: