Android中Volley获取Django登录Cookie并设置到后续请求的实现
核心思路
Django登录成功后会在响应头的Set-Cookie字段返回csrftoken和sessionid,我们需要从响应头提取这两个值并持久化保存,后续请求时在请求头中携带Cookie字段(包含这两个值)以及X-CSRFToken字段(对应csrftoken值)。
完整代码实现
1. 自定义JsonObjectRequest获取响应头
先定义一个能监听响应头的自定义请求类,方便获取Set-Cookie:
import com.android.volley.NetworkResponse; import com.android.volley.Response; import com.android.volley.toolbox.JsonObjectRequest; import org.json.JSONObject; import java.util.Map; public class CustomJsonObjectRequest extends JsonObjectRequest { private OnHeadersReceivedListener headersListener; public interface OnHeadersReceivedListener { void onHeadersReceived(Map<String, String> headers); } public CustomJsonObjectRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener, OnHeadersReceivedListener headersListener) { super(method, url, jsonRequest, listener, errorListener); this.headersListener = headersListener; } @Override protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { // 触发响应头监听 if (headersListener != null) { headersListener.onHeadersReceived(response.headers); } return super.parseNetworkResponse(response); } }
2. 修改登录方法,提取并保存Cookie
在你的Activity中初始化SharedPreferences存储Cookie,然后修改test()方法:
import android.content.SharedPreferences; import android.os.Bundle; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.Volley; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; public class LoginActivity extends AppCompatActivity { private SharedPreferences sharedPref; private SharedPreferences.Editor editor; private String UEmail; // 需提前赋值用户邮箱 private String UPassword; // 需提前赋值用户密码 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); // 初始化SharedPreferences用于保存Cookie sharedPref = getSharedPreferences("AppCookiePrefs", MODE_PRIVATE); editor = sharedPref.edit(); } private void test() { RequestQueue requestQueue = Volley.newRequestQueue(this); String url_ = "https://xxxx.com/api/BF"; Map<String, String> params = new HashMap<>(); params.put("Email", UEmail); params.put("Password", UPassword); JSONObject JOParams = new JSONObject(params); CustomJsonObjectRequest JORequest = new CustomJsonObjectRequest( Request.Method.POST, url_, JOParams, response -> { try { String status_ = response.getString("Status"); if (status_.equals("OK_")) { Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { Toast.makeText(this, "数据解析错误", Toast.LENGTH_SHORT).show(); } }, error -> Toast.makeText(this, "连接失败", Toast.LENGTH_LONG).show(), headers -> { // 从响应头获取Set-Cookie String setCookie = headers.get("Set-Cookie"); if (setCookie != null) { // 解析csrftoken和sessionid String csrfToken = extractCookieValue(setCookie, "csrftoken"); String sessionId = extractCookieValue(setCookie, "sessionid"); // 保存到SharedPreferences if (csrfToken != null) { editor.putString("csrftoken", csrfToken); } if (sessionId != null) { editor.putString("sessionid", sessionId); } editor.apply(); } }); requestQueue.add(JORequest); } // 从Set-Cookie字符串中提取指定Cookie的值 private String extractCookieValue(String setCookie, String cookieName) { String[] cookies = setCookie.split(";"); for (String cookie : cookies) { cookie = cookie.trim(); if (cookie.startsWith(cookieName + "=")) { return cookie.substring(cookieName.length() + 1); } } return null; } }
3. 后续请求携带Cookie和CSRF Token
发起后续请求时,从SharedPreferences取出保存的值,添加到请求头:
private void sendSubsequentRequest() { RequestQueue requestQueue = Volley.newRequestQueue(this); String url = "https://xxxx.com/api/your-subsequent-api"; // 从SharedPreferences获取保存的Cookie值 String csrfToken = sharedPref.getString("csrftoken", ""); String sessionId = sharedPref.getString("sessionid", ""); JsonObjectRequest request = new JsonObjectRequest( Request.Method.GET, url, null, response -> { // 处理后续请求响应逻辑 }, error -> { // 处理请求错误逻辑 }) { @Override public Map<String, String> getHeaders() { Map<String, String> headers = new HashMap<>(); // 添加Cookie头 if (!csrfToken.isEmpty() && !sessionId.isEmpty()) { headers.put("Cookie", "csrftoken=" + csrfToken + "; sessionid=" + sessionId); } // 添加X-CSRFToken头(Django的POST/PUT/DELETE请求必须携带) if (!csrfToken.isEmpty()) { headers.put("X-CSRFToken", csrfToken); } return headers; } }; requestQueue.add(request); }
注意事项
- 若为跨域场景,需确保Django后端配置
CSRF_TRUSTED_ORIGINS包含你的应用域名/IP - HTTPS请求下Cookie的
Secure属性会生效,需保证请求协议一致 - Cookie的
HttpOnly属性不影响Volley从响应头读取值,无需额外处理
内容的提问来源于stack exchange,提问作者rahim
相关产品推荐
相关产品推荐

