如何在PowerShell中通过REST使用OAuth登录禁用明文基础认证的JIRA?
解决JIRA Server OAuth认证访问问题
首先纠正一个小问题:你调用的API路径有误,正确的JIRA Agile API路径应该是/rest/agile/1.0/issue/test-1,而非/jira-software/REST/agile/1.0/issue/test-1,路径大小写和前缀都需要调整。
针对JIRA Server不再支持Basic Auth的情况,我们可以通过OAuth 1.0a完成认证,以下是完整的配置和调用步骤:
一、JIRA Server端配置OAuth应用链接
- 登录JIRA管理员后台,进入应用管理 > 应用链接
- 点击创建应用链接,输入任意一个占位URL(比如
http://localhost:8081,仅用于初始化配置),点击继续 - 在应用链接配置页,填写应用名称(例如
PowerShell OAuth Client),勾选创建传入链接,点击下一步 - 填写OAuth核心配置:
- 消费者密钥:自定义唯一标识(例如
powershell-jira-oauth) - 消费者名称:与应用名称一致即可
- 公钥:后续生成RSA公钥后,将公钥内容粘贴此处
- 点击保存
- 消费者密钥:自定义唯一标识(例如
二、生成RSA密钥对(用于OAuth签名)
在PowerShell中执行以下命令生成密钥对,保存到本地文件:
# 创建RSA加密服务实例 $rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider(2048) # 导出私钥(带私钥的XML格式) $rsa.ToXmlString($true) | Out-File "C:\temp\jira-oauth-private.xml" # 导出公钥(仅公钥的XML格式) $rsa.ToXmlString($false) | Out-File "C:\temp\jira-oauth-public.xml"
打开公钥文件,去掉<RSAKeyValue>等XML标签,仅保留中间的Base64字符串,粘贴到JIRA的公钥配置字段中。
三、获取OAuth访问令牌
1. 获取请求令牌
# 加载本地私钥 $privateKeyXml = Get-Content "C:\temp\jira-oauth-private.xml" -Raw $rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider $rsa.FromXmlString($privateKeyXml) # 构建OAuth基础参数 $oauthParams = @{ oauth_consumer_key = "powershell-jira-oauth" # 替换为你设置的消费者密钥 oauth_signature_method = "RSA-SHA1" oauth_timestamp = [int][double]::Parse((Get-Date -UFormat %s)) oauth_nonce = [System.Guid]::NewGuid().ToString().Replace("-", "") oauth_version = "1.0" oauth_callback = "oob" # 桌面客户端固定用oob } # 生成签名基字符串 $requestTokenUrl = "http://jiraserver:8080/plugins/servlet/oauth/request-token" $sortedParams = $oauthParams.GetEnumerator() | Sort-Object Name | ForEach-Object { "$($_.Key)=$([Uri]::EscapeDataString($_.Value))" } $baseString = "GET&$([Uri]::EscapeDataString($requestTokenUrl))&$([Uri]::EscapeDataString($sortedParams -join "&"))" # 生成RSA签名 $signatureBytes = [System.Text.Encoding]::ASCII.GetBytes($baseString) $signature = [Convert]::ToBase64String($rsa.SignData($signatureBytes, [System.Security.Cryptography.HashAlgorithmName]::SHA1, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)) $oauthParams["oauth_signature"] = [Uri]::EscapeDataString($signature) # 构建Authorization请求头 $authHeaderParts = $oauthParams.GetEnumerator() | ForEach-Object { "$($_.Key)=`"$($_.Value)`"" } $authHeader = "OAuth $($authHeaderParts -join ", ")" # 发送请求获取请求令牌 $response = Invoke-RestMethod -Uri $requestTokenUrl -Headers @{Authorization = $authHeader} -Method Get -AllowUnencryptedAuthentication $requestTokenData = [System.Web.HttpUtility]::ParseQueryString($response) $oauthToken = $requestTokenData["oauth_token"] $oauthTokenSecret = $requestTokenData["oauth_token_secret"]
2. 手动授权令牌
将上述代码得到的$oauthToken值复制,在浏览器中打开JIRA授权页面:
http://jiraserver:8080/plugins/servlet/oauth/authorize?oauth_token=$oauthToken
登录JIRA账号后点击授权,记录页面返回的验证码(verifier code)。
3. 交换访问令牌
# 构建带验证码的OAuth参数 $accessTokenParams = @{ oauth_consumer_key = "powershell-jira-oauth" oauth_signature_method = "RSA-SHA1" oauth_timestamp = [int][double]::Parse((Get-Date -UFormat %s)) oauth_nonce = [System.Guid]::NewGuid().ToString().Replace("-", "") oauth_version = "1.0" oauth_token = $oauthToken oauth_verifier = "替换为你获取的验证码" } # 生成签名基字符串 $accessTokenUrl = "http://jiraserver:8080/plugins/servlet/oauth/access-token" $sortedAccessParams = $accessTokenParams.GetEnumerator() | Sort-Object Name | ForEach-Object { "$($_.Key)=$([Uri]::EscapeDataString($_.Value))" } $accessBaseString = "GET&$([Uri]::EscapeDataString($accessTokenUrl))&$([Uri]::EscapeDataString($sortedAccessParams -join "&"))" # 生成签名 $accessSignatureBytes = [System.Text.Encoding]::ASCII.GetBytes($accessBaseString) $accessSignature = [Convert]::ToBase64String($rsa.SignData($accessSignatureBytes, [System.Security.Cryptography.HashAlgorithmName]::SHA1, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)) $accessTokenParams["oauth_signature"] = [Uri]::EscapeDataString($accessSignature) # 构建Authorization头 $accessAuthHeaderParts = $accessTokenParams.GetEnumerator() | ForEach-Object { "$($_.Key)=`"$($_.Value)`"" } $accessAuthHeader = "OAuth $($accessAuthHeaderParts -join ", ")" # 交换获取永久访问令牌 $accessResponse = Invoke-RestMethod -Uri $accessTokenUrl -Headers @{Authorization = $accessAuthHeader} -Method Get -AllowUnencryptedAuthentication $accessTokenData = [System.Web.HttpUtility]::ParseQueryString($accessResponse) $finalOAuthToken = $accessTokenData["oauth_token"] $finalOAuthTokenSecret = $accessTokenData["oauth_token_secret"]
四、使用OAuth令牌调用JIRA API
# 构建API请求的OAuth参数 $apiParams = @{ oauth_consumer_key = "powershell-jira-oauth" oauth_signature_method = "RSA-SHA1" oauth_timestamp = [int][double]::Parse((Get-Date -UFormat %s)) oauth_nonce = [System.Guid]::NewGuid().ToString().Replace("-", "") oauth_version = "1.0" oauth_token = $finalOAuthToken } # 目标API地址 $apiUrl = "http://jiraserver:8080/rest/agile/1.0/issue/test-1" # 生成签名基字符串 $sortedApiParams = $apiParams.GetEnumerator() | Sort-Object Name | ForEach-Object { "$($_.Key)=$([Uri]::EscapeDataString($_.Value))" } $apiBaseString = "GET&$([Uri]::EscapeDataString($apiUrl))&$([Uri]::EscapeDataString($sortedApiParams -join "&"))" # 生成签名 $apiSignatureBytes = [System.Text.Encoding]::ASCII.GetBytes($apiBaseString) $apiSignature = [Convert]::ToBase64String($rsa.SignData($apiSignatureBytes, [System.Security.Cryptography.HashAlgorithmName]::SHA1, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)) $apiParams["oauth_signature"] = [Uri]::EscapeDataString($apiSignature) # 构建Authorization头 $apiAuthHeaderParts = $apiParams.GetEnumerator() | ForEach-Object { "$($_.Key)=`"$($_.Value)`"" } $apiAuthHeader = "OAuth $($apiAuthHeaderParts -join ", ")" # 发送API请求 $issueData = Invoke-RestMethod -Uri $apiUrl -Headers @{Authorization = $apiAuthHeader} -ContentType "application/json" -AllowUnencryptedAuthentication $issueData
注意事项
- 保存好私钥文件和最终的访问令牌/密钥,后续调用API可直接复用,无需重复授权流程
- 确认JIRA Server已启用OAuth 1.0a:在管理员后台进入系统 > 安全 > OAuth检查配置
- 若JIRA Server版本较新,需确保用户账号有API访问权限
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

