Xamarin Forms调用Axelor Rest服务时持续返回401未授权状态
问题:Xamarin Forms连接Axelor服务器登录成功后调用接口返回401未授权
使用Xamarin Forms应用连接Axelor服务器,登录请求返回成功并获取到JSESSIONID,但后续调用数据接口时始终返回HTTP 401未授权状态,浏览器测试则可得到正确响应。相关代码如下:
Login login = new() { UserName = Constants.Login, Password = Constants.Password }; // Build authentication string byte[] bytes = Encoding.UTF8.GetBytes($"{login.UserName}:{login.Password}"); string authorizationString = Convert.ToBase64String(bytes); // Add headers to the HTTP client httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationString); // Build HTTP message and send, strRoot = login.jsp string url = $"{Constants.RestBaseUrl}/{strRoot}"; HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url); var sessionResponse = await httpClient.SendAsync(message); /* sessionResponse.IsSuccessStatusCode = true, and sessionResponse.Headers = { Set-Cookie: JSESSIONID=E5EA31C3A5CBDF0A1C4B05ED2230679E; Path=/Gradle___com_axelor___axelor_erp_6_3_0_war; HttpOnly Date: Mon, 14 Nov 2022 19:40:04 GMT } */ sessionResponse.Headers.ToList().ForEach(x => httpClient.DefaultRequestHeaders.Add(x.Key, x.Value.FirstOrDefault())); var rt = $"{Constants.RestBaseUrl}/ws/rest/com.axelor.apps.poultryfarming.db.Hatchery"; var response = await httpClient.GetAsync(rt); var returnValue = await response.Content.ReadAsStringAsync(); /* returnValue : <!doctype html><html lang="en"><head><title>HTTP Status 401 – Unauthorized</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 401 – Unauthorized</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The request has not been applied because it lacks valid authentication credentials for the target resource.</p><hr class="line" /><h3>Apache Tomcat/8.5.73</h3></body></html> */ var stat = response.StatusCode; // return: Unauthorized var cc = response.IsSuccessStatusCode; return returnValue; } catch (Exception e) { throw; }
问题原因与解决方法
1. Cookie处理逻辑错误
直接将响应头中的Set-Cookie添加到HttpClient默认请求头的方式不符合HTTP规范,Axelor服务器无法识别这种方式传递的JSESSIONID。浏览器会自动管理Cookie会话,但HttpClient需要通过CookieContainer来正确维护会话Cookie。
2. 修正后的代码
初始化HttpClient时配置CookieContainer,它会自动保存登录响应中的JSESSIONID,后续请求会自动携带该Cookie:
// 初始化带Cookie容器的HttpClient var handler = new HttpClientHandler(); handler.CookieContainer = new CookieContainer(); var httpClient = new HttpClient(handler); Login login = new() { UserName = Constants.Login, Password = Constants.Password }; // 构建Basic认证字符串 byte[] bytes = Encoding.UTF8.GetBytes($"{login.UserName}:{login.Password}"); string authorizationString = Convert.ToBase64String(bytes); // 添加Basic认证头 httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationString); // 发送登录请求 string url = $"{Constants.RestBaseUrl}/{strRoot}"; var sessionResponse = await httpClient.PostAsync(url, null); // 无需手动处理Set-Cookie,CookieContainer自动管理会话 // 调用数据接口 var rt = $"{Constants.RestBaseUrl}/ws/rest/com.axelor.apps.poultryfarming.db.Hatchery"; var response = await httpClient.GetAsync(rt); var returnValue = await response.Content.ReadAsStringAsync(); var stat = response.StatusCode; var cc = response.IsSuccessStatusCode; return returnValue; } catch (Exception e) { throw; }
3. 额外检查项
- 确认
Constants.RestBaseUrl与浏览器请求的地址完全一致,包括上下文路径(比如/Gradle___com_axelor___axelor_erp_6_3_0_war) - 检查Axelor服务器的跨域配置,确保允许Xamarin应用的访问来源
- 验证登录端点
login.jsp是否为Axelor对应版本的正确登录路径,部分版本可能使用/login端点
内容的提问来源于stack exchange,提问作者dal
相关产品推荐
相关产品推荐

