使用Ktor 2.3.3(Kotlin)拉取Azure工作项遇401未授权问题求助
问题分析与解决方案
你的问题出在Authorization请求头的构造方式错误,Azure DevOps的Basic认证要求将: + PAT令牌的字符串整体进行Base64编码,而非分开编码后拼接。
错误点说明
你当前的代码分别对:和PAT令牌做Base64编码再拼接,这会生成不符合要求的认证字符串,直接导致401 Unauthorized:
"Basic ${Base64.getEncoder().encodeToString(":".toByteArray())}${Base64.getEncoder().encodeToString(patToken.toByteArray())}"
修正后的代码
import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.request.* import io.ktor.serialization.kotlinx.json.* import java.util.* object AzureDevOpsClient { private const val BASE_URL = "https://mydevops.com" // 补充完整协议头https:// private const val API_VERSION = "6.0" private val client = HttpClient() { install(ContentNegotiation) { json() } } suspend fun getWorkItems(patToken: String, ids: List<Int>): String { val url = "$BASE_URL?ids=${ids.joinToString(",")}&api-version=$API_VERSION" // 正确构造:将":PAT令牌"整体做Base64编码 val authToken = Base64.getEncoder().encodeToString(":$patToken".toByteArray(Charsets.UTF_8)) return client.get(url) { header("Authorization", "Basic $authToken") }.body<String>() } }
额外注意事项
- 确保
BASE_URL包含完整协议头(如https://),否则Ktor无法正确解析请求地址。 - 可添加错误处理逻辑,方便调试认证问题:
import io.ktor.client.statement.* import io.ktor.http.* // 修改getWorkItems函数 val response = client.get(url) { header("Authorization", "Basic $authToken") } if (response.status == HttpStatusCode.Unauthorized) { throw IllegalStateException("认证失败,请检查PAT令牌权限或有效性") } return response.body<String>() - 确认PAT令牌拥有Work Items读取权限,且未过期。
内容的提问来源于stack exchange,提问作者Kerry
相关产品推荐
相关产品推荐

