Powershell HTTP Post 到服务总线队列 returns 401
Powershell HTTP Post to Service Bus Queue returns 401
尝试向我设置的服务总线队列提交消息,并不断收到 401 Unauthorized return。
我已经尝试使用此方法自行配置 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
两者都给我一个 401 未经授权的错误
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.
您不需要使用 Get-AzServiceBusNamespace 来获取命名空间名称,因为您已经将其作为用户输入。
参见 post 编辑。
令牌过期时间未转换为 UTC,使其始终过期,此外 SaS 令牌配置字符串的格式不正确。
尝试向我设置的服务总线队列提交消息,并不断收到 401 Unauthorized return。
我已经尝试使用此方法自行配置 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
两者都给我一个 401 未经授权的错误
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.
您不需要使用 Get-AzServiceBusNamespace 来获取命名空间名称,因为您已经将其作为用户输入。
参见 post 编辑。
令牌过期时间未转换为 UTC,使其始终过期,此外 SaS 令牌配置字符串的格式不正确。