You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin安卓APP带基础认证的POST请求报com.android.volley.ServerError求助

解决Volley调用带Basic Auth的REST服务时出现ServerError的问题

你已经排查了URL、认证头、参数和防火墙这些关键点,但Postman正常、Volley报错的情况,往往是请求细节和Postman没对齐导致的。下面给你几个具体的排查方向和修复方案:

1. 先揪出具体的HTTP状态码

ServerError只是个笼统的报错,咱先在错误回调里打印出具体的状态码,这能帮你快速定位是认证失败(401)、参数格式错了(400)还是服务器内部问题(5xx):

Response.ErrorListener { error ->
    val statusCode = error.networkResponse?.statusCode ?: -1
    Toast.makeText(this, "Error: ${error.toString()} | 状态码: $statusCode", Toast.LENGTH_LONG).show()
    textView.text = "请求失败!状态码: $statusCode"
}

2. 验证Basic Auth的编码是否正确

你用Base64.NO_WRAP是对的(避免换行符破坏认证头),但可以和Postman的结果对比一下:

  • 打开Postman的「Authorization」标签,选Basic Auth输入账号密码,再切到「Headers」标签,复制Authorization头的值
  • 对比你代码里生成的Basic xxx字符串是否完全一致,如果不一样,检查账号密码有没有特殊字符(比如空格、中文),编码时要确保用UTF-8格式(代码里可以显式指定Charsets.UTF_8避免系统默认编码坑)

3. 确保请求体格式和Postman完全匹配

Postman能正常请求,先确认它用的是哪种请求体类型:

如果Postman用的是表单提交(x-www-form-urlencoded)

你当前的getParams()写法没问题,但可以显式添加Content-Type头,避免Volley默认头可能的不一致:

override fun getHeaders(): MutableMap<String, String> {
    val headers = HashMap<String, String>()
    val authorizationString = String.format("%s:%s", "username", "password")
    val authorizationByte = authorizationString.toByteArray(Charsets.UTF_8) // 显式指定UTF-8编码
    val base64Encoded = Base64.encodeToString(authorizationByte, Base64.NO_WRAP)
    headers["Authorization"] = "Basic $base64Encoded"
    headers["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8"
    return headers
}

如果Postman用的是JSON提交(Raw/JSON)

那你当前的StringRequest就不适用了,得换成JsonObjectRequest,把参数放到JSON请求体里,同时设置正确的Content-Type:

val jsonObjectRequest = object : JsonObjectRequest(
    Request.Method.POST, url,
    JSONObject(mapOf("username" to "username", "password" to "password")), // 构造JSON请求体
    Response.Listener<JSONObject> { response ->
        textView.text = "响应内容: ${response.toString().substring(0, 500)}"
    },
    Response.ErrorListener { error ->
        val statusCode = error.networkResponse?.statusCode ?: -1
        Toast.makeText(this, "Error: ${error.toString()} | 状态码: $statusCode", Toast.LENGTH_LONG).show()
        textView.text = "请求失败!状态码: $statusCode"
    }) {
    override fun getHeaders(): MutableMap<String, String> {
        val headers = HashMap<String, String>()
        val authorizationString = String.format("%s:%s", "username", "password")
        val authorizationByte = authorizationString.toByteArray(Charsets.UTF_8)
        val base64Encoded = Base64.encodeToString(authorizationByte, Base64.NO_WRAP)
        headers["Authorization"] = "Basic $base64Encoded"
        headers["Content-Type"] = "application/json; charset=utf-8"
        return headers
    }
}
// 添加到请求队列
queue.add(jsonObjectRequest)

4. 调整重试策略,避免干扰排查

你已经设置了45秒超时,这挺好,但可以先关闭重试,避免多次请求打乱排查节奏:

stringRequest.setRetryPolicy(
    DefaultRetryPolicy(
        45000,
        0, // 关闭重试
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
    )
)

5. 最后再核对一遍URL和参数

确保代码里的ApiUrls.CustomerAuthenticate和Postman的URL完全一致(包括HTTP/HTTPS、端口、路径里的大小写),还有getParams()里的参数键名要和Postman完全匹配(很多后端对参数名大小写敏感!)


内容的提问来源于stack exchange,提问作者Mostafa Khodakarami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 09:27:50