我正在尝试上传本地文件,但是当我执行POST请求时,出现invalid CSRF (Cross Site Request Forgery) token, make sure all requests include a valid '_csrf_token' param or 'x-csrf-token' header
错误
我已经尝试调用此函数
def csrf_token(conn) do
Plug.Conn.get_session(conn, :csrf_token)
end
我的.html.eex:
<form action="/accounts/new/csv-validator" method="post"
enctype="multipart/form-data">
<input type="hidden" name="_csrf_token" value="<%= @get_csrf_token() %>">
<input class="form-control input-bordered" id="user_photo" name="user[photo]" type="file">
</form>
预期结果:成功使用有效的csrf令牌进行POST
凤凰版本:v1.3.4
答案 0 :(得分:0)
在Phoenix --add-modules
中是一个宏,即它是宏函数的名称:
@实际上是一个将@key转换为Map.get(assigns,:key)的宏。
我实际上认为该报价有误,应显示为:
@实际上是一个将@key转换为Keyword.get(assigns, :key)。
@
来自这里:
assigns
https://hexdocs.pm/phoenix/Phoenix.Controller.html#render/3
结果,如果您这样调用render:
render(conn, template, assigns)
然后在render(conn, "page.html", message: "hello", answer: "yello")
|_______________________________|
^
|
assigns (a keyword list)
模板中,如果您编写page.html
,则Phoenix将用@message
替换它,其结果为Keyword.get(assigns, :message)
。
那应该表明在模板中写"hello"
是胡说八道。相反,您需要做的是这样的:
@get_csrf_token()
然后,您可以在模板中编写def your_action(conn, _params) do
render(conn, "page.html", csrf: csrf_token(conn) )
end
来插入令牌。
答案 1 :(得分:0)
我发现@7stud 很有教育意义并且很有帮助,但我没有给这个堆栈留下明确的解决方案;所以我想我会试一试。
使用 Phoenix 渲染 EEx 模板时,有很多选项。在这个问题中,@Leka 似乎没有使用 Phoenix.HTML,但我会将它与其他选项一起列出。
没有 Phoenix.HTML:
<form method="post" action"...">
<input type="hidden" name="_csrf_token" value="<%= Plug.CSRFProtection.get_csrf_token() %>">
...
</form>
Phoenix 的版本做了同样的事情:
<form method="post" action"...">
<input type="hidden" name="_csrf_token" value="<%= Phoenix.Controller.get_csrf_token() %>">
...
</form>
使用 Phoenix.HTML,各种形式的 form_for 在 POST 时会自动执行此操作(这是默认操作):
<%= form_for @conn, "..." %>
...
</form>
我无法从问题中 100% 判断出来,但看起来 @Leka 可能正在定义自定义 CSRF 函数。如果是这样,只要在相应的 Phoenix 视图文件中定义了该函数,就可以使用“@”宏从模板中调用该函数。
除非需要超出 Plug 提供的自定义代码,否则这种方法是不必要的。与@7stud 在渲染中使用assigns 参数的方法相同。再次,不要不尊重@7stud 的回答;这可能是对他们对@Leka 试图做的事情的解释的直接回应。