Sinatra Songs API 教程:使用 Auth0 添加授权保护 CRUD API
在这篇文章中,我们将学习如何使用 Auth0 为 Sinatra API 添加授权功能,并保护其端点。我们将构建一个名为 Sinatra Songs API 的歌曲 CRUD API,展示如何通过 Sinatra 框架实现基本的 API 功能,并结合 Auth0 来实现安全性。
项目要求
在本项目中,我们将使用以下技术和工具:
- Ruby(推荐版本 3.0 或更高)
- Sinatra(轻量级 Ruby Web 框架)
- Auth0(身份验证和授权服务)
- Postman 或
curl(用于测试 API)
构建歌曲 API
创建项目
首先,在终端中创建一个名为 sinatra-auth0-songs-api 的新文件夹,并将其设为当前目录。
mkdir sinatra-auth0-songs-api
cd sinatra-auth0-songs-api
安装 Sinatra
创建一个 Gemfile 文件,用于管理项目依赖:
# Gemfile
source 'https://rubygems.org'
ruby File.read('.ruby-version').stripgem 'sinatra', '~> 3.0', '>= 3.0.2'
gem 'puma'
然后,创建 .ruby-version 文件,指定 Ruby 版本:
3.1.2
运行以下命令安装依赖:
bundle install
至此,Sinatra 已成功安装!🎉
创建歌曲模型
在项目中创建一个 models 文件夹,并添加 song.rb 文件:
# models/song.rb
# frozen_string_literal: true
class Song
attr_accessor :id, :name, :url def initialize(id, name, url)
@id = id
@name = name
@url = url
end def to_json(*_args)
{ id: id, name: name, url: url }.to_json
end
end
实现 CRUD API
创建一个 api.rb 文件,作为 API 的主入口:
delete ‘/songs/:id’ do
{ todo: :implementation }.to_json
end
require 'sinatra'
require 'json'
before do
content_type 'application/json'
end
get '/songs' do
{ todo: :implementation }.to_json
end
get '/songs/:id' do
{ todo: :implementation }.to_json
end
post '/songs' do
{ todo: :implementation }.to_json
end
put '/songs/:id' do
{ todo: :implementation }.to_json
end
delete '/songs/:id' do
{ todo: :implementation }.to_json
end
运行以下命令启动服务器:
ruby api.rb
服务器启动后,访问 http://localhost:4567 即可测试 API。
使用 songs.json 填充数据
为了给 API 提供数据,我们将使用一个名为 songs.json 的文件,该文件包含 Frank Sinatra 的热门歌曲。创建一个 helpers 文件夹,并添加 songs_helper.rb 文件:
# helpers/songs_helper.rb
# frozen_string_literal: true
require_relative '../models/song'
require 'json'class SongsHelper
def self.songs
filepath = File.join(File.dirname(__FILE__), '../songs.json')
file = File.read(filepath)
data = JSON.parse(file)['songs'] data.map { |song| Song.new(song['id'], song['name'], song['url']) } end
end
在 api.rb 中加载 songs.json 数据:
# api.rb
require_relative 'helpers/songs_helper'
songs ||= SongsHelper.songsget '/songs' do
songs.to_json
end
添加授权功能
配置 Auth0
- 登录 Auth0 管理控制台。
- 创建一个新的 API:
- 名称:Sinatra Songs API
- 标识符:
https://sinatra-auth0-songs-api - 签名算法:RS256
记录下 标识符 和 域名,稍后会用到。
安装依赖
在 Gemfile 中添加以下依赖:
gem 'dotenv'
gem 'jwt'
运行以下命令安装依赖:
bundle install
创建 .env 文件,存储 Auth0 的配置信息:
AUTH0_DOMAIN=your-auth0-domain
AUTH0_AUDIENCE=https://sinatra-auth0-songs-api
验证访问令牌
创建一个 auth0_client_helper.rb 文件,用于验证访问令牌:
jwks_hash = JSON.parse(jwks_response.body).transform_keys(&:to_sym)
decoded_token = decode_token(token, jwks_hash)
Response.new(decoded_token, nil)
rescue JWT::VerificationError, JWT::DecodeError
Response.new(nil, Error.new(‘Bad credentials’, 401))
end
end
require 'jwt'
require 'net/http'
class Auth0ClientHelper
Error = Struct.new(:message, :status)
Response = Struct.new(:decoded_token, :error)
def self.domain_url
"https://#{ENV['AUTH0_DOMAIN']}/"
end
def self.decode_token(token, jwks_hash)
JWT.decode(token, nil, true, {
algorithm: 'RS256',
iss: domain_url,
verify_iss: true,
aud: ENV['AUTH0_AUDIENCE'],
verify_aud: true,
jwks: { keys: jwks_hash[:keys] }
})
end
def self.get_jwks
jwks_uri = URI("#{domain_url}.well-known/jwks.json")
Net::HTTP.get_response(jwks_uri)
end
def self.validate_token(token)
jwks_response = get_jwks
return Response.new(nil, Error.new('Unable to verify credentials', :internal_server_error)) unless jwks_response.is_a?(Net::HTTPSuccess)
jwks_hash = JSON.parse(jwks_response.body).transform_keys(&:to_sym)
decoded_token = decode_token(token, jwks_hash)
Response.new(decoded_token, nil)
rescue JWT::VerificationError, JWT::DecodeError
Response.new(nil, Error.new('Bad credentials', 401))
end
end
保护 API 端点
在 api.rb 中添加授权逻辑:
# api.rb
require_relative 'helpers/auth0_client_helper'
helpers do
def authorize!
token = token_from_request
validation_response = Auth0ClientHelper.validate_token(token)
halt validation_response.error.status, { message: validation_response.error.message }.to_json if validation_response.error
end def token_from_request
authorization_header = request.env['HTTP_AUTHORIZATION']
halt 401, { message: 'Authorization header missing' }.to_json unless authorization_header schema, token = authorization_header.split
halt 401, { message: 'Invalid authorization header format' }.to_json unless schema.downcase == 'bearer' token
end
endbefore method: %i[post put delete] do
authorize!
end
总结
通过本文,我们学习了如何使用 Sinatra 构建一个基本的 CRUD API,并结合 Auth0 实现基于令牌的授权功能。希望这篇文章对您有所帮助!如果您对其他 Ruby 框架感兴趣,欢迎在评论中分享您的想法!
原文链接: https://auth0.com/blog/add-authorization-to-sinatra-api-using-auth0/
最新文章
- 了解如何从零开始使用Node.js构建REST API
- 长时间运行操作的 API 设计最佳实践:GraphQL 与 REST
- 免费使用微博热搜API进行数据分析的教程
- Python调用文本相似度比较API:精准识别重复内容的实用指南
- Claude 与 GitHub Copilot 限流机制与代码生成能力对比
- 发票API如何赋能小型企业金融科技的未来
- 什么是 REST API?示例、用途和挑战
- 全面增强API网关安全:策略与实践
- 如何在移动应用上进行API测试 – Mobot应用测试平台
- 移动应用API测试 | 如何使用Testsigma进行测试?
- Java API:定义、包、类型及示例详解
- 在 Power Apps 中使用 Web API 的挑战 – CloudThat