Skip to content

Instantly share code, notes, and snippets.

@mimosa
Last active January 11, 2017 07:49
Show Gist options
  • Save mimosa/697272a175a3bb6b61ac to your computer and use it in GitHub Desktop.
Save mimosa/697272a175a3bb6b61ac to your computer and use it in GitHub Desktop.
Rails + JWT
  • 使用前:
    • �使用�前
  • 使用后:
    • 正确回传:
    • 使用后
    • 验证 (客户端)
    • 验证成功
    • 提交错误:
    • 验证错误

Install

services/token_provider.rb

middleware/json_web_token.rb

Configure

config/application.rb

  # API 模板路径
  config.middleware.use Rack::Config do |env|
    env['api.tilt.root'] ||= Rails.root.join('api', 'views')
    env['api.jwt.secret'] ||= Rails.application.secrets.secret_key_base
    env['api.jwt.path_pattern'] ||= /\/api\/v(.*)/
    env['api.jwt.param_name'] ||= '_'
  end
  # ...
  config.middleware.use JsonWebToken

Gemfile

gem 'jwt', '~> 1.5', '>= 1.5.2'
gem 'multi_json', '~> 1.11', '>= 1.11.2'
# -*- encoding: utf-8 -*-
class JsonWebToken
def initialize(app)
@app = app
end
def call(env)
is_jwt = false
unless env['api.jwt.secret'].blank?
request = Rack::Request.new(env)
jwt = TokenProvider.new(env['api.jwt.secret'])
path_pattern = env['api.jwt.path_pattern'] || /\/api\/v(.*)/
param_name = env['api.jwt.param_name'] || '_'
if request.path =~ path_pattern && request.params[param_name].present?
is_jwt = true
# 还原参数
env["QUERY_STRING"] = jwt.load(request.params[param_name]).shift.try(:to_query)
end
end
status, headers, response = @app.call(env)
# 是否干预输出
if is_jwt && headers['Content-Type'] == 'application/json'
body = jwt.dump MultiJson.load(response.body.shift)
response = [body]
headers['Content-Type'] = 'text/plain'
headers['Content-Length'] = body.length.to_s
end
[status, headers, response]
rescue JWT::VerificationError
[401, { 'Content-Type' => 'text/plain' }, 'Signature verification raiseed']
end
end
# -*- encoding: utf-8 -*-
class TokenProvider
def initialize(secret)
@secret = secret
end
def load(str)
JWT.decode(str, @secret)
end
def dump(obj, expires_in = 24.hours.from_now)
obj = obj.dup
obj['exp'] = expires_in.to_i
JWT.encode(obj, @secret)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment