监护人文件不允许我生成 JWT 令牌



我正在使用{:guardian,"~> 1.0"}为我的项目生成令牌,但它给了我一个错误。

这是我的监护人文件的代码

defmodule Dailyploy.Guardian do
use Guardian, otp_app: :dailyploy
def subject_for_token(user, _claims) do
sub = to_string(user.id)
{:ok, sub}
end
def subject_for_token(_, _) do
{:error, :reason_for_error}
end
def resource_from_claims(claims) do
id = claims["sub"]
resource = Dailyploy.Accounts.get_user!(id)
{:ok,  resource}
end
def resource_from_claims(_claims) do
{:error, :reason_for_error}
end
end

它向我展示了一个subject_for_token的错误。 此子句无法匹配,因为第 4 行的前一个子句始终与 Elixir 匹配

有人可以解释为什么它不起作用吗?

编译器抱怨是因为您对subject_for_token的两个定义是相同的,它们都期望完全相同的参数。

若要解决此问题,请在第一个定义中明确表示要接收User结构:

def subject_for_token(%User{id: id}, _claims) do
{:ok, to_string(id)}
end
def subject_for_token(_, _) do
{:error, :reason_for_error}
end

resource_from_claims也可以这样说;两个函数将匹配完全相同的参数。这也可以修复:

def resource_from_claims(%{"sub" => sub}) do
resource = Dailyploy.Accounts.get_user!(sub)
{:ok, resource}
end
def resource_from_claims(_claims) do
{:error, :reason_for_error}
end

有人可以解释一下为什么这不起作用吗?

当你调用一个函数时,elixir 从定义中的第一个函数子句开始,并尝试将函数调用中指定的参数与函数定义中的参数匹配。如果没有匹配项,elixir 就会尝试下一个函数子句。找到匹配项后,将执行相应的函数体。如果所有函数子句都不匹配,则会出现function_clause错误。

让我们来看一个例子。 如果你写:

def go({1, 2}, :cat) do
IO.puts "I must have matched the function call."
end

然后你可以像这样调用该函数:

iex(2)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok

但是,如果您尝试:

ex(3)> A.go("hello", 10)
** (FunctionClauseError) no function clause matching in A.go/2    
The following arguments were given to A.go/2:
# 1
"hello"
# 2
10
a.ex:2: A.go/2

您会收到函数子句错误,因为go()定义的函数子句与函数调用不匹配

function call:     A.go("hello", 10)
|       |
{1,2} = "hello  |       | :cat = 10
V       V
function def:    def go({1, 2}, :cat) do

go()函数调用中唯一能匹配函数定义中元组{1, 2}的参数是元组{1, 2},函数调用中唯一能匹配函数定义中原子:cat的参数是原子:cat

但是,函数定义中的变量与任何内容匹配。合法变量名的一些例子是:xy_x_。 因此,如果您像这样定义go()

def go(_x, _y) do
IO.puts "I must have matched the function call."
end

然后两个函数调用将匹配:

iex(3)> c "a.ex"          
warning: redefining module A (current version defined in memory)
a.ex:1
[A]
iex(4)> A.go("hello", 10)
I must have matched the function call.
:ok
iex(5)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok

如果将第二个函数子句添加到 go() 定义中:

def go(_x, _y) do
IO.puts "I must have matched the function call."
end
def go(_, _) do
IO.puts "I will never match"
end

第一个函数子句仍将匹配任意两个参数,并且由于这种情况,第二个函数子句将永远不会执行 - 因此编译器会给您一个警告,这相当于:

跆拳道? 你为什么要在第二个函数子句中潦草地写下所有这些垃圾 当它永远不会匹配,因此永远不会执行时?!抓紧!

当您在函数定义中进行模式匹配时,事情会变得更加棘手,例如:

def go(%{a: val}=map, x) do

请参阅此处了解其工作原理。

相关内容

  • 没有找到相关文章

最新更新