Screencast: APIs schützen

Es gibt viele Möglichkeiten den Zugriff auf APIs zu schützen. In diesem Screencast zeigt Ryan erst einen möglichen Schutz über HTTP Basic Auth und später über Tokens die als Parameter übertragen werden.

 

Downloads in verschiedenen Formaten:

mp4
mp4
webm
ogg

 

Resourcen:

terminal

[bash]
rails g model api_key access_token
curl http://localhost:3000/api/products -I
curl http://localhost:3000/api/products -u ‚admin:secret‘
curl ‚http://localhost:3000/api/products?access_token=123‘ -I
curl http://localhost:3000/api/products -H ‚Authorization: Token token="c576f0136149a2e2d9127b3901015545"‘
[/bash]

api/v1/products_controller.rb

[ruby]
# http_basic_authenticate_with name: "admin", password: "secret"
before_filter :restrict_access

private

# def restrict_access
# api_key = ApiKey.find_by_access_token(params[:access_token])
# head :unauthorized unless api_key
# end

def restrict_access
authenticate_or_request_with_http_token do |token, options|
ApiKey.exists?(access_token: token)
end
end
[/ruby]

models/api_key.rb

[ruby]
before_create :generate_access_token

private

def generate_access_token
begin
self.access_token = SecureRandom.hex
end while self.class.exists?(access_token: access_token)
end
[/ruby]

Screencast: Versionierung von REST APIs

APIs sollten konsistent sein. Dies ist allerdings schwer zu bewerkstelligen wenn verschiedene Formate unterstützt werden und/oder die APIs sich weiterentwickeln. In diesem Screencast zeigt Ryan wie eine API-Versionierung über die URL oder HTPP-Header realisiert werden können.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

terminal

[bash]
rails g migration change_products_released_on
rake db:migrate
cp -R app/controllers/api/v1 app/controllers/api/v2
curl -H ‚Accept: application/vnd.example.v1‘ http://localhost:3000/api/products
[/bash]

routes.rb

[ruby]
require ‚api_constraints‘

Store::Application.routes.draw do
namespace :api, defaults: {format: ‚json‘} do
scope module: :v1, constraints: ApiConstraints.new(version: 1) do
resources :products
end
scope module: :v2, constraints: ApiConstraints.new(version: 2, default: true) do
resources :products
end
end

resources :products
root to: ‚products#index‘
end
[/ruby]

lib/api_constraints.rb

[ruby]
class ApiConstraints
def initialize(options)
@version = options[:version]
@default = options[:default]
end

def matches?(req)
@default || req.headers[‚Accept‘].include?("application/vnd.example.v#{@version}")
end
end
[/ruby]

app/controllers/api/v1/products_controller.rb

[ruby]
module Api
module V1
class ProductsController < ApplicationController
class Product < ::Product
# Note: this does not take into consideration the create/update actions for changing released_on
def as_json(options = {})
super.merge(released_on: released_at.to_date)
end
end

respond_to :json

def index
respond_with Product.all
end

def show
respond_with Product.find(params[:id])
end

def create
respond_with Product.create(params[:product])
end

def update
respond_with Product.update(params[:id], params[:product])
end

def destroy
respond_with Product.destroy(params[:id])
end
end
end
end
[/ruby]