Azure Powershell HTTP Post到服务总线队列返回401

Azure Powershell HTTP Post到服务总线队列返回401,azure,powershell,rest,azure-servicebus-queues,sas-token,Azure,Powershell,Rest,Azure Servicebus Queues,Sas Token,试图向我设置的服务总线队列提交消息,并不断收到401未经授权的返回 我已经尝试使用此方法自己配置SAS令牌 $ResourceGroupName = 'myResourceGroup' $NameSpaceName = "serviceBusNameSpace" $QueueName = "myQueueName" $PolicyName = "RootManageSharedAccessKey" $body = "test message" $Namespace = (Get-AzServi

试图向我设置的服务总线队列提交消息,并不断收到401未经授权的返回

我已经尝试使用此方法自己配置SAS令牌

$ResourceGroupName = 'myResourceGroup'
$NameSpaceName = "serviceBusNameSpace"
$QueueName = "myQueueName"
$PolicyName = "RootManageSharedAccessKey"
$body = "test message"

$Namespace = (Get-AzServiceBusNamespace -ResourceGroupName $ResourceGroupName -Name $namespacename).Name
$key = (Get-AzServiceBusKey -ResourceGroupName $ResourceGroupName -Namespace $namespacename -Name $PolicyName).PrimaryKey

$origin = [DateTime]"1/1/1970 00:00" 
$Expiry = (Get-Date).AddMinutes(5)    

#compute the token expiration time.
$diff = New-TimeSpan -Start $origin -End $Expiry 
$tokenExpirationTime = [Convert]::ToInt32($diff.TotalSeconds)

#Create a new instance of the HMACSHA256 class and set the key to UTF8 for the size of $Key
$hmacsha = New-Object -TypeName System.Security.Cryptography.HMACSHA256
$hmacsha.Key = [Text.Encoding]::UTF8.GetBytes($Key)

$scope = "https://$Namespace.servicebus.windows.net/"
#create the string that will be used when cumputing the hash
$stringToSign = [Web.HttpUtility]::UrlEncode($scope) + "`n" + $tokenExpirationTime

#Compute hash from the HMACSHA256 instance we created above using the size of the UTF8 string above.
$hash = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
#Convert the hash to base 64 string
$signature = [Convert]::ToBase64String($hash)
$fullResourceURI = "https://$Namespace.servicebus.windows.net/$QueueName"
#create the token
$token = [string]::Format([Globalization.CultureInfo]::InvariantCulture, `
         "SharedAccessSignature sr={0}sig={1}&se={2}&skn={3}", `
         [Web.HttpUtility]::UrlEncode($fullResourceURI), `
         [Web.HttpUtility]::UrlEncode($signature), `
         $tokenExpirationTime, $PolicyName) 

$headers = @{ "Authorization" = "$token"; "Content-Type" = "application/atom+xml;type=entry;charset=utf-8" }
$uri = "https://$Namespace.servicebus.windows.net/$QueueName/messages"
$headers.Add("BrokerProperties", "{}")

#Invoke-WebRequest call.
Invoke-WebRequest -Uri $uri -Headers $headers -Method Post -Body $body -UseBasicParsing
我还尝试通过Az.ServiceBus中的内置cmdlet生成它

$ResourceGroupName = 'myResourceGroup'
$NameSpaceName = "serviceBusNameSpace"
$QueueName = "myQueueName"
$PolicyName = "RootManageSharedAccessKey"

$body = "test message"
$expiry = (Get-Date).AddHours(2)
$authRule = Get-AzServiceBusAuthorizationRule -ResourceGroupName $ResourceGroupName -Namespace $NamespaceName
$token = New-AzServiceBusAuthorizationRuleSASToken -AuthorizationRuleId $authRule.Id -KeyType Primary -ExpiryTime $Expiry

$headers = @{ "Authorization" = "SharedAccessSignature $($token.SharedAccessSignature)"; "Content-Type" = "application/atom+xml;type=entry;charset=utf-8" }
$uri = "https://$Namespace.servicebus.windows.net/$QueueName/messages"
$headers.Add("BrokerProperties", "{}")

#Invoke-WebRequest call.
Invoke-WebRequest -Uri $uri -Headers $headers -Method Post -Body $body -UseBasicParsing
两者都给了我一个错误

Invoke-WebRequest : The remote server returned an error: (401) Unauthorized.
At line:9 char:17
+ ... $response = Invoke-WebRequest -Uri $uri -Headers $headers -Method Pos ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
我不知道还能做什么。是否需要为azure门户内的队列配置设置

已经找到了解决方案。除了格式错误的SAS签名外,UTC时间最初是在发送令牌之前过期的

最终代码编辑如下

$key = (Get-AzServiceBusKey -ResourceGroupName $ResourceGroupName -Namespace $namespacename -Name $PolicyName).PrimaryKey

$origin = [DateTime]"1/1/1970 00:00" 
$Expiry = (Get-Date).AddMinutes(20)
$Expiry = $Expiry.ToUniversalTime()    

#compute the token expiration time.
$diff = New-TimeSpan -Start $origin -End $Expiry 
$tokenExpirationTime = [Convert]::ToInt32($diff.TotalSeconds)


$uri = "https://$Namespace.servicebus.windows.net/$QueueName/messages"
$scope = "https://$Namespace.servicebus.windows.net/$QueueName"
#create the string that will be used when cumputing the hash
$stringToSign = [Web.HttpUtility]::UrlEncode($scope) + "`n" + $tokenExpirationTime

#Create a new instance of the HMACSHA256 class and set the key to UTF8 for the size of $Key
$hmacsha = New-Object -TypeName System.Security.Cryptography.HMACSHA256
$hmacsha.Key = [Text.Encoding]::UTF8.GetBytes($Key)


#Compute hash from the HMACSHA256 instance we created above using the size of the UTF8 string above.
$hash = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
#Convert the hash to base 64 string
$signature = [Convert]::ToBase64String($hash)

#create the token
$token = [string]::Format([Globalization.CultureInfo]::InvariantCulture, `
        "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", `
        [Web.HttpUtility]::UrlEncode($scope), `
        [Web.HttpUtility]::UrlEncode($signature), `
        $tokenExpirationTime, $PolicyName) 

$headers = @{ "Authorization" = "$token"}
$headers.Add("Content-Type", "application/atom+xml;type=entry;charset=utf-8")

#Invoke-WebRequest call.
Invoke-WebRequest -Uri $uri -Headers $headers -Method Post -Body $body -UseBasicParsing

我对你的脚本做了一些修改,效果很好

$ResourceGroupName = 'myResourceGroup'
$Namespace = "serviceBusNameSpace"
$QueueName = "myQueueName"
$PolicyName = "RootManageSharedAccessKey"
$body = "test message"

$key = (Get-AzServiceBusKey -ResourceGroupName $ResourceGroupName -Namespace $Namespace -Name $PolicyName).PrimaryKey

$origin = [DateTime]"1/1/1970 00:00" 
$Expiry = (Get-Date).AddMinutes(5)    

#compute the token expiration time.
$diff = New-TimeSpan -Start $origin -End $Expiry 
$tokenExpirationTime = [Convert]::ToInt32($diff.TotalSeconds)

#Create a new instance of the HMACSHA256 class and set the key to UTF8 for the size of $Key
$hmacsha = New-Object -TypeName System.Security.Cryptography.HMACSHA256
$hmacsha.Key = [Text.Encoding]::UTF8.GetBytes($Key)

#create the string that will be used when cumputing the hash
$stringToSign = [Web.HttpUtility]::UrlEncode($Namespace) + "`n" + $tokenExpirationTime

#Compute hash from the HMACSHA256 instance we created above using the size of the UTF8 string above.
$hash = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
#Convert the hash to base 64 string
$signature = [Convert]::ToBase64String($hash)

#create the token
$token = [string]::Format([Globalization.CultureInfo]::InvariantCulture, `
        "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", `
        [Web.HttpUtility]::UrlEncode($Namespace), `
        [Web.HttpUtility]::UrlEncode($signature), `
        $tokenExpirationTime, $PolicyName) 

$headers = @{ "Authorization" = "$token"; "Content-Type" = "application/atom+xml;type=entry;charset=utf-8" }
$uri = "https://$Namespace.servicebus.windows.net/$QueueName/messages"
$headers.Add("BrokerProperties", "{}")

#Invoke-WebRequest call.
Invoke-WebRequest -Uri $uri -Headers $headers -Method Post -Body $body -UseBasicParsing
我所作的更改如下:

  • 您不需要创建范围变量。您需要将$Namespace传递给stringToSign

  • 您不需要使用获取AzServiceBusNamespace来获取名称空间名称,因为您已经将其作为用户输入


  • 我对你的脚本做了一些修改,效果很好

    $ResourceGroupName = 'myResourceGroup'
    $Namespace = "serviceBusNameSpace"
    $QueueName = "myQueueName"
    $PolicyName = "RootManageSharedAccessKey"
    $body = "test message"
    
    $key = (Get-AzServiceBusKey -ResourceGroupName $ResourceGroupName -Namespace $Namespace -Name $PolicyName).PrimaryKey
    
    $origin = [DateTime]"1/1/1970 00:00" 
    $Expiry = (Get-Date).AddMinutes(5)    
    
    #compute the token expiration time.
    $diff = New-TimeSpan -Start $origin -End $Expiry 
    $tokenExpirationTime = [Convert]::ToInt32($diff.TotalSeconds)
    
    #Create a new instance of the HMACSHA256 class and set the key to UTF8 for the size of $Key
    $hmacsha = New-Object -TypeName System.Security.Cryptography.HMACSHA256
    $hmacsha.Key = [Text.Encoding]::UTF8.GetBytes($Key)
    
    #create the string that will be used when cumputing the hash
    $stringToSign = [Web.HttpUtility]::UrlEncode($Namespace) + "`n" + $tokenExpirationTime
    
    #Compute hash from the HMACSHA256 instance we created above using the size of the UTF8 string above.
    $hash = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
    #Convert the hash to base 64 string
    $signature = [Convert]::ToBase64String($hash)
    
    #create the token
    $token = [string]::Format([Globalization.CultureInfo]::InvariantCulture, `
            "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", `
            [Web.HttpUtility]::UrlEncode($Namespace), `
            [Web.HttpUtility]::UrlEncode($signature), `
            $tokenExpirationTime, $PolicyName) 
    
    $headers = @{ "Authorization" = "$token"; "Content-Type" = "application/atom+xml;type=entry;charset=utf-8" }
    $uri = "https://$Namespace.servicebus.windows.net/$QueueName/messages"
    $headers.Add("BrokerProperties", "{}")
    
    #Invoke-WebRequest call.
    Invoke-WebRequest -Uri $uri -Headers $headers -Method Post -Body $body -UseBasicParsing
    
    我所作的更改如下:

  • 您不需要创建范围变量。您需要将$Namespace传递给stringToSign

  • 您不需要使用获取AzServiceBusNamespace来获取名称空间名称,因为您已经将其作为用户输入

  • 请参见后期编辑

    令牌过期时间未转换为UTC,因此除了SaS令牌配置字符串格式不正确外,它始终过期。

    请参阅后期编辑


    令牌过期时间未转换为UTC,因此除了SaS令牌配置字符串格式不正确外,它始终过期。

    在第一种情况下,您是否可以尝试将
    范围设置为
    https://$Namespace.servicebus.windows.net/$QueueName
    而不是
    https://$Namespace.servicebus.windows.net/
    ?@GauravMantri AIS我也尝试过该路由,并且在第一种情况下也产生了相同的“401”未经授权错误,您可以尝试将
    范围设置为
    https://$Namespace.servicebus.windows.net/$QueueName
    而不是
    https://$Namespace.servicebus.windows.net/
    ?@GauravMantri AIS我也尝试过该路由,它产生了相同的“401”未经授权的错误我已经针对我的服务总线名称空间中的队列测试了您的代码,但仍然收到401未经授权的响应。此密钥是服务总线命名空间中的共享访问策略密钥,我是否需要命名空间中队列上的共享访问策略中的密钥?此外,根据这一点,完整资源URI需要位于共享访问签名令牌中,不仅是命名空间中,而且我们在stringToSign中将$scope作为完整资源URI发送,我们得到的错误与你提到的相同。另外,当我把它改为名称空间名称时,它对我起了作用。我已经更新了代码。现在检查获取密钥时“Namespace”变量的键入错误。我已重新测试了代码,仍收到“401 Unauthorized”响应我已针对我的服务总线命名空间中的队列测试了您的代码,仍收到401 Unauthorized响应。此密钥是服务总线命名空间中的共享访问策略密钥,我是否需要命名空间中队列上的共享访问策略中的密钥?此外,根据这一点,完整资源URI需要位于共享访问签名令牌中,不仅是命名空间中,而且我们在stringToSign中将$scope作为完整资源URI发送,我们得到的错误与你提到的相同。另外,当我把它改为名称空间名称时,它对我起了作用。我已经更新了代码。现在检查一下,在获取密钥时键入“Namespace”变量时出错。我已经重新测试了代码,仍然收到“401 Unauthorized”响应