ruby - 为 azure 服务总线/eventhubs 生成有效的授权 header

标签 ruby azure azure-eventhub

我正在尝试在 ruby​​ 脚本中使用 SAS 身份验证,但我不断从事件中心收到 401(访问被拒绝)响应,看来我错误地生成了 SAS token 。

下面是我使用过的代码,它基于https://azure.microsoft.com/en-us/documentation/articles/service-bus-sas-overview/我重写为 ruby​​ 的 Javascript 示例(请注意,这可能不符合惯用语)

require "optparse"
require "CGI"
require 'openssl'
require "base64"
require "Faraday"
require 'Digest'

def generateToken(url,keyname,keyvalue)
    encoded = CGI::escape(url)
    ttl = (Time.now + 60*5).to_i
    signature = "#{encoded}\n#{ttl}".encode('utf-8')
    # puts signature
    key = Base64.strict_decode64(keyvalue)
    dig  = OpenSSL::HMAC.digest('sha256', key, signature)
    # dig = Digest::HMAC.digest(signature, key, Digest::SHA256)
    hash = CGI.escape(Base64.strict_encode64(dig))
    # puts hash
    return "SharedAccessSignature sig=#{hash}&se=#{ttl}&skn=#{keyname}&sr=#{encoded}" 
end

def build_connection(url,token)
    conn = Faraday.new(:url => url) do |faraday|
        faraday.request  :url_encoded             # form-encode POST params
        faraday.response :logger                  # log requests to STDOUT
        faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
    end
    conn.headers['Content-Type'] = 'application/json'
    conn.headers['Authorization'] = token
    return conn
end


if __FILE__ == $0
    ARGV << '-h' if ARGV.empty?
    options = {}
    OptionParser.new do |opts|
        opts.banner = "Usage: generateSasToken.rb [options]"
        opts.on('-u URL', '--url URL', 'url for access') { |v| options[:url] = v }
        opts.on('--keyname NAME','set key name') { |v| options[:keyname] = v }
        opts.on('--key KEY','set key value') { |v| options[:keyvalue] = v }
        opts.on_tail("-h", "--help", "Show this message") do
            puts opts
            exit
        end
    end.parse!
    token = generateToken(options[:url],options[:keyname],options[:keyvalue])
    puts token
    conn = build_connection(options[:url],token)
    puts conn.headers
    response =  conn.post do |req|
                    req.body = '{"temprature":50}'
                    req.headers['content-length'] = req.body.length.to_s
                end
    puts response
end

任何有助于理解 token 为何不正确的帮助都会很棒

最佳答案

将我的代码与 python sdk 进行比较后,这是生成 token 的正确方法:

require "optparse"
require "CGI"
require 'openssl'
require "base64"
require "Faraday"
require 'Digest'

def generateToken(url,keyname,keyvalue)
    encoded = CGI::escape(url)
    ttl = (Time.now + 60*5).to_i
    signature = "#{encoded}\n#{ttl}"
    # puts signature
    key = keyvalue
    #dig  = OpenSSL::HMAC.digest('sha256', key, signature)
    dig = Digest::HMAC.digest(signature, key, Digest::SHA256)
    hash = CGI.escape(Base64.strict_encode64(dig))
    # puts hash
    return "SharedAccessSignature sig=#{hash}&se=#{ttl}&skn=#{keyname}&sr=#{encoded}" 
end

def build_connection(url,token)
    conn = Faraday.new(:url => url) do |faraday|
        faraday.request  :url_encoded             # form-encode POST params
        faraday.response :logger                  # log requests to STDOUT
        faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
    end
    conn.headers['Content-Type'] = 'application/json'
    conn.headers['Authorization'] = token
    return conn
end


if __FILE__ == $0
    ARGV << '-h' if ARGV.empty?
    options = {}
    OptionParser.new do |opts|
        opts.banner = "Usage: generateSasToken.rb [options]"
        opts.on('-u URL', '--url URL', 'url for access') { |v| options[:url] = v }
        opts.on('--keyname NAME','set key name') { |v| options[:keyname] = v }
        opts.on('--key KEY','set key value') { |v| options[:keyvalue] = v }
        opts.on_tail("-h", "--help", "Show this message") do
            puts opts
            exit
        end
    end.parse!
    token = generateToken(options[:url],options[:keyname],options[:keyvalue])
    conn = build_connection(options[:url],token)
    puts conn.headers
    response =  conn.post do |req|
                    req.body = '{"temprature":50}'
                    req.headers['content-length'] = req.body.length.to_s
                end
    puts response
end

这比预期简单得多,不需要编码为 utf8 或解码 key 。

关于ruby - 为 azure 服务总线/eventhubs 生成有效的授权 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36691938/

相关文章:

ruby-on-rails - 如何在 Rails 4.2 中使用 has_secure_password 加密密码

ruby-on-rails - "No explicit conversion of Symbol into String"用于 rails 4.0.1 中的新记录(仅限)

ruby - 如何在 Ruby 中进行就地放置

scala - 如何在 Spark Streaming 中验证 azure iot hub 的连接字符串?

azure - 与 Azure 事件中心通信时出现 EPOCH 错误

ruby-on-rails - 解析包含 GMT 偏移时间的时区名称字符串

azure - Application Insights 报告每个服务器请求的重复事件

node.js - 定义 Azure blob 流的大小限制,即截断文件

azure - 将 azure 中的存储帐户防火墙中的跨租户子网列入白名单

azure-eventhub - Azure 事件中心是否保证至少交付一次?