我有一个使用Guardian进行JWT身份验证的应用程序。当用户登录时,响应包含正文中的jwt。然后,前端(即SPA)将jwt存储在localStorage中,并将其附加到从那里发送的每个请求的Authorization
标头。然后,服务器使用Guardian的内置验证插件验证这一点:
pipeline :api do
plug :accepts, ["json"]
plug Guardian.Plug.VerifyHeader, realm: "Bearer"
end
我想改变它,以便将服务器作为安全cookie(Secure
和{{1}发送到前端,而不是将JWT存储在localStorage(不安全)中。设置)。然后我希望Guardian从cookie中读取jwt,而不是从HttpOnly
标题中读取。
Guardian是否支持此功能?
这是我的SessionController Authorization
函数:
create
答案 0 :(得分:0)
只需使用加密的会话cookie。 JWT令牌不打算存储在本地(在localStorage或cookie中),因为你只是放弃了JWT的用途。
在您的代码段中,您似乎使用JWT令牌替代会话Cookie。为什么不直接使用会话cookie?
答案 1 :(得分:0)
我认为您误解了JWT的工作原理。它是否暴露无关紧要。登录时获取JWT,然后在页面上重新加载/刷新。它在后端签名。整个要点就是能够拥有一个可以在FE中传递的对象,而不必暴露您的SKs
答案 2 :(得分:0)
更新:这是与Guardian 1.0一起使用的(如果可以的话,应该使用!)。
我认为您可以执行以下操作:
defmodule MyApp.SessionController do
def login(conn, params) do
# your code to find the user based on auth strategy here
{:ok, jwt, _} = MyApp.Guardian.encode_and_sign(user)
conn = put_session(conn, :auth_token, jwt)
# send your response...
end
end
将在Cookie上使用HttpOnly
和Secure
标志。这样存储客户端应该没问题。
要获取用户,您可能需要编写自己的小插头,但是您的MyApp.Guardian
模块可能看起来像这样:
defmodule MyApp.Guardian do
use Guardian, otp_app: :my_app
alias MyApp.Accounts
def subject_for_token(%Accounts.Human{} = human, _claims) do
{:ok, to_string(human.id)}
end
def subject_for_token(_, _) do
{:error, :resource_not_found}
end
def resource_from_claims(%{"sub" => sub}) do
case Accounts.find_human(sub) do
nil -> {:error, :resource_not_found}
human -> {:ok, human}
end
end
def resource_from_claims(_) do
{:error, :resource_not_found}
end
end