如何在Django中向SAP Business One Service Layer发起后续请求
解决Django调用SAP Business One Service Layer会话失效问题
你遇到的301错误是因为后续请求未携带SAP Service Layer的有效会话凭证。SAP B1 Service Layer登录成功后会返回会话ID(SessionId),同时在响应头中设置会话Cookie,后续请求必须携带其中一种凭证才能通过身份验证。以下是两种可行的解决方案:
方式一:使用requests.Session自动维护会话Cookie
requests.Session会自动保存登录后的Cookie,后续请求复用同一个会话对象即可,无需手动处理会话凭证。
修改登录函数
def AuthSAP(request): sap_url = "https://sap_url.com:50000/b1s/v2/Login" headers = { "authkey": "XXXXXXXXXXXXXXXXXXXX", "Accept": "*/*", "Content-Type": "text/plain", } data = { "CompanyDB": "XXXXXXXX", "UserName": "XXXXXXXX", "Password": "XXXXXXX" } # 创建会话对象 session = requests.Session() response = session.post(sap_url, headers=headers, json=data) response_data = response.json() # 将SAP会话Cookie转为字典存入Django会话 request.session['sap_session_cookies'] = session.cookies.get_dict() print("JSON Response ", response_data) return HttpResponse(response_data, content_type='application/json')
后续请求函数
def GetOpenOrders(request): sap_url = "https://sap_url.com:50000/b1s/v2/Orders" # 从Django会话中取出SAP会话Cookie sap_cookies = request.session.get('sap_session_cookies') if not sap_cookies: return HttpResponse({"error": "未登录SAP系统"}, content_type='application/json', status=401) headers = { "authkey": "XXXXXXXXXXXXXXXXXXXX", "Accept": "*/*", "Content-Type": "text/plain", } # 创建会话并加载保存的Cookie session = requests.Session() session.cookies.update(sap_cookies) response = session.get(sap_url, headers=headers) response_data = response.json() # 检查会话是否超时,超时则清除本地存储的Cookie if 'error' in response_data and response_data['error']['code'] == '301': del request.session['sap_session_cookies'] return HttpResponse(response_data, content_type='application/json', status=401) print("JSON Response ", response_data) return HttpResponse(response_data, content_type='application/json')
方式二:手动携带SessionId请求头
登录成功后从响应JSON中提取SessionId,后续请求在headers中添加该字段。
修改登录函数
def AuthSAP(request): sap_url = "https://sap_url.com:50000/b1s/v2/Login" headers = { "authkey": "XXXXXXXXXXXXXXXXXXXX", "Accept": "*/*", "Content-Type": "text/plain", } data = { "CompanyDB": "XXXXXXXX", "UserName": "XXXXXXXX", "Password": "XXXXXXX" } response = requests.post(sap_url, headers=headers, json=data) response_data = response.json() # 提取SessionId并存入Django会话 if 'SessionId' in response_data: request.session['sap_session_id'] = response_data['SessionId'] print("JSON Response ", response_data) return HttpResponse(response_data, content_type='application/json')
后续请求函数
def GetOpenOrders(request): sap_url = "https://sap_url.com:50000/b1s/v2/Orders" # 从Django会话中取出SessionId sap_session_id = request.session.get('sap_session_id') if not sap_session_id: return HttpResponse({"error": "未登录SAP系统"}, content_type='application/json', status=401) headers = { "authkey": "XXXXXXXXXXXXXXXXXXXX", "Accept": "*/*", "Content-Type": "text/plain", "SessionId": sap_session_id # 添加SessionId到请求头 } response = requests.get(sap_url, headers=headers) response_data = response.json() # 检查会话超时,超时则清除本地存储的SessionId if 'error' in response_data and response_data['error']['code'] == '301': del request.session['sap_session_id'] return HttpResponse(response_data, content_type='application/json', status=401) print("JSON Response ", response_data) return HttpResponse(response_data, content_type='application/json')
额外注意事项
- SAP Service Layer会话默认30分钟超时,建议在后续请求中捕获
301错误,触发自动重新登录逻辑。 - 生产环境中,建议对存储在Django会话中的SAP会话信息进行加密,避免安全风险。
- Django会话会自动隔离不同用户的会话数据,多用户场景下无需额外处理。
内容的提问来源于stack exchange,提问作者Daniel25th
相关产品推荐
相关产品推荐

