Xcode模拟器请求Django后端报403 Forbidden,Canvas预览正常求助
问题描述
用SwiftUI开发登录页面,后端基于Django框架,两者均在本地运行。登录接口在Postman和Xcode Canvas预览中可正常工作,但在Xcode模拟器中运行时返回403 Forbidden错误。此前功能正常,未修改代码却突然失效,关闭Django的CSRF中间件后问题仍存在。
SwiftUI代码
func sendOTP(phoneNumber: String) -> Bool{ if phoneNumber.count != 11 { return false } guard let url=URL(string: "http://127.0.0.1:8000/login/") else { return false // fatalError("Missing URL") } var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") // Most likely you want to add some token here // request.setValue("token", forHTTPHeaderField: "Authorization") // request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") let requestData = [ "request_type": "sms_auth", "phone_number": phoneNumber, ] let encoder = JSONEncoder() if let encodedData = try? encoder.encode(requestData) { urlRequest.httpBody = encodedData } else { return false } let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, error in if let error = error { print("Request error: ", error) return } guard let response = response as? HTTPURLResponse else {return} if response.statusCode == 200 { guard let data = data else {return} DispatchQueue.main.async { do { let decodedData = try JSONDecoder().decode(KCWebRes<String>.self, from: data) } catch let error { print("Error decoding: ", error) } } } } dataTask.resume() return true }
Django代码
class Login(APIView): def post(self, request): if not "phont_number" not in request.data: pass phone_number = request.data["phone_number"] if not KCUser.phone_number_auth(phone_number): ret = login_sc.fail return JsonResponse(ret) con_redis = get_redis_connection(alias='verify_codes') request_type = request.data["request_type"] if request_type == "sms_auth": sms_code = "%06d" % random.randint(0, 999999) if con_redis.exists("sms_send_" + phone_number): ret = login_sc.sms_fail return JsonResponse(ret) rds_pl = con_redis.pipeline() try: rds_pl.setex("sms_send_" + phone_number, 60, 1) rds_pl.setex("sms_code_" + phone_number, 300, sms_code) rds_pl.execute() except Exception as e: print(e) sms_auth(phone_number, sms_code) ret = login_sc.sms_sent return JsonResponse(ret) elif request_type == "login": request_sms_code = request.data["sms_code"] _code = con_redis.get("sms_code_" + phone_number).decode() if not request_sms_code or not _code: ret = login_sc.sms_code_error return JsonResponse(ret) if request_sms_code != _code: ret = login_sc.sms_code_error return JsonResponse(ret) else: if KCUser.objects.filter(phone_number=phone_number).count() == 0: user = KCUser.objects.create_user( phone_number=phone_number, username=phone_number, password="qazwsxedc" # TODO password ) user.save() else: user = KCUser.objects.get(phone_number=phone_number) login(request, user) ret = login_sc.success ret["data"] = KCUserSerializer(user).data return JsonResponse(ret) state = login_sc.fail return JsonResponse(state)
解决方案
1. 修正Django代码中的拼写与逻辑错误
你的Django代码存在两处明显问题:
- 拼写错误:
"phont_number"应为"phone_number" - 逻辑错误:
if not "phont_number" not in request.data:的双重否定逻辑混乱,正确写法应为if "phone_number" not in request.data:
修正后的代码片段:
def post(self, request): if "phone_number" not in request.data: ret = login_sc.fail return JsonResponse(ret) phone_number = request.data["phone_number"] # 后续代码保持不变
该错误可能导致后端处理请求时逻辑异常,返回非预期的错误状态码。
2. 替换模拟器访问的IP地址
iOS模拟器中,127.0.0.1指向模拟器自身而非你的电脑,无法访问本地Django服务。需替换为电脑的局域网IP地址:
- 查看电脑局域网IP:Mac在
系统设置-网络中查看,Windows通过ipconfig命令获取 - 修改SwiftUI代码中的URL:
guard let url=URL(string: "http://你的电脑IP:8000/login/") else { return false }
3. 重置iOS模拟器的网络状态
模拟器缓存或网络配置可能异常,重置步骤:
- 打开Xcode,点击顶部菜单
Window > Devices and Simulators - 选中当前使用的模拟器,右键选择
Erase All Content and Settings - 确认后重启模拟器再测试
4. 配置Django的跨域访问(CORS)
即使关闭CSRF中间件,Django默认限制跨域请求,模拟器请求可能被判定为跨域。解决方法:
- 安装django-cors-headers:
pip install django-cors-headers
- 在Django的
settings.py中添加配置:
INSTALLED_APPS = [ # 其他应用 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 放在中间件列表最前面 # 其他中间件 ] CORS_ALLOW_ALL_ORIGINS = True # 开发环境临时使用,生产环境需指定具体域名
5. 查看Django详细日志
启动Django服务时,终端会输出请求的详细日志,查看403错误的具体原因(如CSRF验证细节、权限限制等),可快速定位问题。
内容的提问来源于stack exchange,提问作者wyhn.w
相关产品推荐
相关产品推荐

