Android端Volley调用API出现403 AuthFailureError求助
解决Volley调用API返回AuthFailureError 403的问题(Postman正常但Android异常)
问题描述
同一个API在Postman中可正常获取响应,但在Android设备上用Volley调用时抛出com.android.volley.AuthFailureError 403错误。调用API前需设置25个参数,Postman截图可验证API本身正常。已尝试设置Content-Type、Base64编码、Token校验等方案,问题仍未解决。当前网络调用代码如下:
import android.app.Activity import android.content.Intent import android.util.Base64 import android.util.Log import com.android.volley.* import com.android.volley.toolbox.StringRequest import com.android.volley.toolbox.Volley import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.softnoesis.maxotexmart.login.LoginActivity import com.softnoesis.maxotexmart.utils.AppPreference import com.softnoesis.maxotexmart.utils.CommonUtils import com.softnoesis.maxotexmart.utils.Constant.Companion.NETWORK_API_CALL import com.softnoesis.maxotexmart.utils.Constant.Companion.TAG import org.json.JSONObject import java.lang.reflect.Type class NetworkAPICall { fun CallApplicationWS(mContext: Activity?, NetworkAPICallModel: NetworkAPICallModel, NetworkAPIResponseCallback: NetworkAPIResponseCallback?) { Log.i(TAG, "$NETWORK_API_CALL --> CallApplicationWS") if (NetworkAPICallModel.getCommonUtils().isNetworkAvailable(mContext!!)) try { if (!NetworkAPICallModel.isShowProgress()) NetworkAPICallModel.getCommonUtils().showProgress(mContext) val RequestQueue: RequestQueue = Volley.newRequestQueue(mContext) val StringRequest: StringRequest = object : StringRequest(NetworkAPICallModel.getRequest_type(), NetworkAPICallModel.getApiURL(), Response.Listener<String?> { response -> Log.i(TAG, "$NETWORK_API_CALL --> " + "CallApplicationWS --> response") try{ NetworkAPICallModel.getCommonUtils().hideProgress() if(NetworkAPICallModel.getParserType() != null) { val `object`: Any = Gson().fromJson(response, NetworkAPICallModel.getParserType()) NetworkAPICallModel.setResponseObject(`object`) } NetworkAPIResponseCallback?.onSuccessResponse(JSONObject(response), NetworkAPICallModel) } catch(jsonException: Exception) { NetworkAPICallModel.getCommonUtils().hideProgress() Log.i(TAG, "$NETWORK_API_CALL --> CallApplicationWS --> response --> ${jsonException.message}") try{ NetworkAPICallModel.getCommonUtils().hideProgress() }catch (e: Exception) { NetworkAPICallModel.getCommonUtils().hideProgress() Log.i(TAG, "$NETWORK_API_CALL --> CallApplicationWS --> response --> ${e.message}") } } }, Response.ErrorListener { error -> NetworkAPICallModel.getCommonUtils().hideProgress() Log.i(TAG, "$NETWORK_API_CALL --> CallApplicationWS --> error --> ${error.message}") val response: NetworkResponse = error.networkResponse if (error is ServerError) { try { val intent = Intent(mContext, LoginActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK mContext.startActivity(intent) } catch (e1: Exception) { NetworkAPICallModel.getCommonUtils().hideProgress() Log.i(TAG, "$NETWORK_API_CALL --> CallApplicationWS --> error --> ${e1.message}") } } CommonUtils().hideProgress() CommonUtils().showDialog( mContext, """ Something went wrong! Please try again later! If problem still persist, please drop mail at support@.com """.trimIndent() ).show() }) { override fun getParams(): MutableMap<String, String> { var params: MutableMap<String, String> = HashMap() val type: Type = object : TypeToken<HashMap<String, String>>() {}.type params = Gson().fromJson(NetworkAPICallModel.getJsonObjectRequest().toString(), type) return params } override fun getHeaders(): MutableMap<String, String> { val params: MutableMap<String, String> = HashMap() // headers.put("Authorization", "Bearer " + jetEncryptor.getJwtkey()); if (AppPreference(mContext).isUserLogin()) { params["User-Agent"]="Mozilla/5.0" params["Authorization"] = "Bearer " + AppPreference(mContext).getToken() } return params } } RequestQueue.add(StringRequest) StringRequest.retryPolicy = DefaultRetryPolicy( 0, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT ) } catch (e: Exception) { NetworkAPICallModel.getCommonUtils().hideProgress() Log.i(TAG, "$NETWORK_API_CALL --> CallApplicationWS -->${e.message}") } else { NetworkAPICallModel.getCommonUtils().hideProgress() CommonUtils().showDialog(mContext, "Please check you internet connection").show() } } }
排查与解决建议
1. 完全对比Postman与Volley的请求头
403错误大多源于权限校验不通过,必须把Postman的所有请求头(包括默认隐藏的)和Volley发送的请求头做逐行对比:
- 在Postman中点击「Code」按钮,选择「Kotlin - Volley」生成代码,和你的代码对比请求头、参数构造逻辑
- 检查是否遗漏了Postman中的关键头(比如
Accept、Content-Type,或服务器要求的自定义头) - 当前代码中
getHeaders()仅在用户登录时设置User-Agent和Authorization,若未登录状态下调用该API,这两个头会缺失,可能触发403
2. 验证参数构造的准确性
你通过Gson将JsonObjectRequest转成HashMap作为参数,可能存在以下问题:
- JSON中的数值类型(整数、浮点数)被转成字符串,导致服务器校验不匹配
- 参数键名大小写与服务器要求不一致(Postman可能不区分,但服务器严格校验)
- 打印
getParams()返回的参数Map,和Postman中发送的参数逐一核对,确保键名、值的类型、内容完全一致
3. 确认请求方法与参数传递格式
- 核实API的请求方法(GET/POST):如果是POST请求,Volley的
StringRequest默认用application/x-www-form-urlencoded格式,若Postman使用raw/JSON格式,服务器可能无法解析参数,进而返回403(部分服务器会将参数解析失败判定为权限问题) - 若服务器要求JSON格式的请求体,需重写
getBody()和getBodyContentType()方法,替代getParams():
override fun getBody(): ByteArray { return NetworkAPICallModel.getJsonObjectRequest().toString().toByteArray(charset("UTF-8")) } override fun getBodyContentType(): String { return "application/json; charset=utf-8" }
4. 确保Token的有效性与正确传递
- 打印
AppPreference(mContext).getToken()获取的Token,和Postman中使用的Token完全对比,确认一致 - 检查Token是否过期,或是否需要配合其他参数(如设备ID、时间戳)使用
- 部分服务器会校验Token签名,需确保Token生成的算法、密钥和服务器端一致
5. 调整重试策略的超时时间
当前代码设置超时时间为0,会导致请求立即超时,可能被服务器判定为异常请求拦截,建议设置合理的超时时间:
StringRequest.retryPolicy = DefaultRetryPolicy( 15000, // 15秒超时 DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT )
6. 抓包调试请求详情
使用Charles或Fiddler抓包,查看Volley发送的完整请求(包括请求头、参数、请求体),和Postman的请求做对比,这是定位差异最直接的方法。
内容的提问来源于stack exchange,提问作者user2357113
相关产品推荐
相关产品推荐

