0Pricing
Elixir & Phoenix: Scalable Backend Development · 课时

身份验证与授权策略

使用 JWT 等常见身份验证方法保护 API 端点,并实现授权规则。

身份验证与授权策略 是 CoddyKit 上的免费 Elixir & Phoenix: Scalable Backend Development 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Elixir & Phoenix: Scalable Backend Development 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Elixir & Phoenix: Scalable Backend Development 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Securing Your API Endpoints

When building APIs with Phoenix, securing your endpoints is paramount. This ensures only authorized users can access specific resources and perform actions.

We'll explore two key aspects: Authentication (proving who you are) and Authorization (determining what you can do).

What is Authentication?

Authentication is the process of verifying a user's identity. It's how your API confirms that the person or application making a request is who they claim to be.

  • Common methods include username/password, API keys, or tokens.
  • Once authenticated, the user's identity is known to the system.

Token-Based Authentication

For APIs, sending username/password with every request is inefficient and insecure. Token-based authentication is a popular solution.

After initial login, the server issues a unique token. The client then sends this token with subsequent requests to prove its identity, without re-sending credentials.

JSON Web Tokens (JWT)

JSON Web Tokens (JWTs) are a common type of token. They are compact, URL-safe means of representing claims to be transferred between two parties.

A JWT is essentially a string with three parts, separated by dots:

  • Header: Describes the token type and signing algorithm.
  • Payload: Contains the 'claims' (user data, roles, expiration).
  • Signature: Verifies the token's integrity and authenticity.

JWT Header and Payload

Both the Header and Payload are JSON objects, Base64Url-encoded. This encoding makes them safe for URL transmission, but it's not encryption – anyone can read them.

Let's see how to encode a simple Header and Payload in Elixir:

alias Jason
alias Base

defmodule JWTExample do
  def encode_part(data) do
    data
    |> Jason.encode!()
    |> Base.url_encode64(padding: false)
  end

  def main do
    header = %{"alg" => "HS256", "typ" => "JWT"}
    payload = %{"user_id" => 123, "role" => "admin"}

    encoded_header = encode_part(header)
    encoded_payload = encode_part(payload)

    IO.puts "Encoded Header: " <> encoded_header
    IO.puts "Encoded Payload: " <> encoded_payload
  end
end

JWTExample.main()

JWT Signature Explained

The Signature is crucial for security. It's created by taking the encoded Header, the encoded Payload, a secret key, and the algorithm specified in the header, then cryptographically signing them.

This signature ensures the token hasn't been tampered with. If someone changes the header or payload, the signature verification will fail.

Creating & Verifying a JWT

Here's a full Elixir example demonstrating how to combine the parts to create a simple JWT and then verify its integrity. We'll use a secret key for signing.

Notice how `Base.url_decode64` and `:crypto.mac` are used to simulate JWT logic.

alias Jason
alias Base

defmodule JWTService do
  @secret_key "my_super_secret_key_123"

  def create_token(payload) do
    header = %{"alg" => "HS256", "typ" => "JWT"}

    encoded_header = encode_part(header)
    encoded_payload = encode_part(payload)

    signature = sign(encoded_header, encoded_payload)

    "#{encoded_header}.#{encoded_payload}.#{signature}"
  end

  def verify_token(token) do
    [encoded_header, encoded_payload, signature] = String.split(token, ".")
    expected_signature = sign(encoded_header, encoded_payload)

    if signature == expected_signature do
      decoded_payload = encoded_payload |> Base.url_decode64!() |> Jason.decode!()
      {:ok, decoded_payload}
    else
      {:error, "Invalid signature"}
    end
  end

  defp encode_part(data) do
    data
    |> Jason.encode!()
    |> Base.url_encode64(padding: false)
  end

  defp sign(encoded_header, encoded_payload) do
    data_to_sign = "#{encoded_header}.#{encoded_payload}"
    :crypto.mac(:hmac, :sha256, @secret_key, data_to_sign)
    |> Base.url_encode64(padding: false)
  end

  def main do
    payload = %{"user_id" => 456, "role" => "editor", "exp" => 1678886400}
    token = create_token(payload)
    IO.puts "Generated Token: " <> token

    case verify_token(token) do
      {:ok, data} -> IO.puts "Verified! Payload: " <> inspect(data)
      {:error, reason} -> IO.puts "Verification Failed: " <> reason
    end

    # Simulate tampering
    tampered_payload = %{"user_id" => 456, "role" => "admin", "exp" => 1678886400}
    tampered_token = create_token(tampered_payload)
    [h, _p, s] = String.split(tampered_token, ".")
    # Replace the payload but keep original signature
    tampered_token_str = "#{h}." <> (payload |> Jason.encode!() |> Base.url_encode64(padding: false)) <> ".#{s}"
    IO.puts "\nTampered Token: " <> tampered_token_str

    case verify_token(tampered_token_str) do
      {:ok, data} -> IO.puts "Verified (unexpectedly)! Payload: " <> inspect(data)
      {:error, reason} -> IO.puts "Tampering Detected: " <> reason
    end
  end
end

JWTService.main()

What is Authorization?

Once a user is authenticated (we know who they are), Authorization determines what actions they are allowed to perform and what resources they can access.

It's about permissions. For example, an 'admin' user might be able to delete posts, while a 'guest' user can only view them.

Role-Based Access Control (RBAC)

A common authorization strategy is Role-Based Access Control (RBAC).

  • Users are assigned one or more roles (e.g., 'admin', 'editor', 'viewer').
  • Each role has a predefined set of permissions (e.g., 'create_post', 'edit_own_post', 'delete_any_post').
  • When a request comes in, the system checks if the authenticated user's role has the necessary permission for the requested action.

Authorization with Phoenix Plugs

In Phoenix, Plugs are an excellent way to implement authorization logic. A Plug is a modular function that processes requests.

You can create a Plug that checks the user's role (often extracted from a JWT payload) before allowing access to a controller action or an entire scope of routes.

For example, a `RequireAdminPlug` would halt the request if the user's role isn't 'admin'.

JWT & Authz Check

Which of the following statements about JWTs and API security are TRUE?

Summary: Secure Your APIs

You've learned the fundamentals of securing API endpoints!

  • Authentication confirms identity, often using tokens like JWTs.
  • JWTs consist of an encoded Header, Payload, and a cryptographic Signature for integrity.
  • Authorization defines what an authenticated user can do, commonly managed with Role-Based Access Control (RBAC).
  • Phoenix Plugs are ideal for implementing authorization checks in your API routes.

Keep exploring security best practices to build robust and safe applications!

常见问题解答

「身份验证与授权策略」课时是免费的吗?

是的 — 「身份验证与授权策略」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Elixir & Phoenix: Scalable Backend Development 课程的其余内容,请升级到 CoddyKit PRO。 Elixir & Phoenix: Scalable Backend Development 课程共包含 4 节课。

「身份验证与授权策略」这节课中我会学到什么?

使用 JWT 等常见身份验证方法保护 API 端点,并实现授权规则。 你通过在浏览器中直接运行的动手代码来练习 Elixir & Phoenix: Scalable Backend Development,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Elixir & Phoenix: Scalable Backend Development 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Elixir & Phoenix: Scalable Backend Development 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「身份验证与授权策略」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Elixir & Phoenix: Scalable Backend Development 课中编写并运行代码吗?

能。每节 Elixir & Phoenix: Scalable Backend Development 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. API 设计原则与最佳实践
  2. 实现 API 端点与序列化
  3. 身份验证与授权策略
  4. 分页、筛选与 API 版本管理
← 返回 Elixir & Phoenix: Scalable Backend Development