如何实现Firebase认证HTTPS触发云函数及Swift/ObjC客户端调用?
实现仅认证用户可调用的Firebase HTTPS云函数及iOS客户端调用指南
我来帮你一步步搞定这个需求——先把后端的云函数权限控制做好,再教你用Swift和Objective-C客户端怎么调用,两种实现方式(原生HTTPS函数和更省心的Callable封装函数)都给你列清楚,按需选择就行。
一、后端:创建带身份验证的HTTPS云函数
首先得确保你已经初始化了Firebase云函数项目,没弄的话先跑firebase init functions完成初始化。
1. 原生HTTPS函数(手动验证token)
这种方式灵活性更高,需要我们自己处理token的提取和验证,直接上代码:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.protectedHttpsFunction = functions.https.onRequest(async (req, res) => { // 从请求头里拿Authorization字段,格式是「Bearer <用户token>」 const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith("Bearer ")) { res.status(401).send("Unauthorized: 请提供有效的身份令牌"); return; } // 提取出纯token字符串 const idToken = authHeader.split("Bearer ")[1]; try { // 用Firebase Admin SDK验证token的有效性 const decodedToken = await admin.auth().verifyIdToken(idToken); const uid = decodedToken.uid; functions.logger.info(`已认证用户:${uid}`, {structuredData: true}); // 这里写你的业务逻辑,比如查询用户数据、执行操作等 res.status(200).send(`你好,已认证用户 ${uid}!`); } catch (error) { functions.logger.error("令牌验证失败", error); res.status(401).send("Unauthorized: 无效的身份令牌"); } });
写完后部署函数:
firebase deploy --only functions:protectedHttpsFunction
2. Callable Functions(Firebase自动处理验证)
如果不想手动写token验证逻辑,推荐用Callable Functions——Firebase SDK会自动帮你处理身份验证,代码更简洁:
exports.protectedCallableFunction = functions.https.onCall(async (data, context) => { // 直接检查context.auth是否存在,不存在就抛出未认证错误 if (!context.auth) { throw new functions.https.HttpsError( "unauthenticated", "必须在登录状态下调用此函数。" ); } const uid = context.auth.uid; // 这里写你的业务逻辑 return {message: `你好,已认证用户 ${uid}!`}; });
部署方式和上面一样,替换函数名即可。
二、Swift客户端调用方法
先确保你的iOS项目已经集成了Firebase Auth(必须,因为要获取用户token),如果用Callable函数的话还要集成Firebase Functions。
1. 调用原生HTTPS函数
需要先获取当前登录用户的ID token,然后把它放到请求头里发送:
import FirebaseAuth // 获取当前用户的ID token Auth.auth().currentUser?.getIDToken(completion: { token, error in guard let idToken = token, error == nil else { print("获取ID令牌失败:\(error?.localizedDescription ?? "未知错误")") return } // 替换成你的云函数URL(部署后控制台能看到) guard let url = URL(string: "https://<你的地区>-<你的项目ID>.cloudfunctions.net/protectedHttpsFunction") else { print("无效的URL") return } var request = URLRequest(url: url) request.httpMethod = "GET" // 根据你的函数需求改请求方法(POST/PUT等) request.setValue("Bearer \(idToken)", forHTTPHeaderField: "Authorization") // 发送请求 let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("请求出错:\(error.localizedDescription)") return } guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { print("响应无效或状态码错误") if let data = data, let errorMsg = String(data: data, encoding: .utf8) { print("错误信息:\(errorMsg)") } return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print("响应内容:\(responseString)") } } task.resume() })
2. 调用Callable Functions(推荐)
这种方式Firebase SDK会自动帮你附加token,代码更简洁:
import FirebaseFunctions // 初始化Functions实例,指定你的云函数地区(比如asia-east1) let functions = Functions.functions(region: "<你的地区>") // 调用函数,还可以传参数给后端 functions.httpsCallable("protectedCallableFunction").call(["someData": "测试数据"]) { result, error in if let error = error as NSError? { if error.domain == FunctionsErrorDomain { let code = FunctionsErrorCode(rawValue: error.code) let message = error.localizedDescription let details = error.userInfo[FunctionsErrorDetailsKey] print("Callable函数出错:\(code?.rawValue ?? 0),\(message),详情:\(details ?? "")") } return } // 解析后端返回的数据 if let responseData = result?.data as? [String: Any], let message = responseData["message"] as? String { print("后端响应:\(message)") } }
三、Objective-C客户端调用方法
同样分两种方式,先确保项目集成了Firebase Auth和(可选)Firebase Functions。
1. 调用原生HTTPS函数
#import <FirebaseAuth/FirebaseAuth.h> // 获取当前用户的ID token [[FIRAuth auth].currentUser getIDTokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) { if (error) { NSLog(@"获取ID令牌失败:%@", error.localizedDescription); return; } NSURL *url = [NSURL URLWithString:@"https://<你的地区>-<你的项目ID>.cloudfunctions.net/protectedHttpsFunction"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"GET"; [request setValue:[NSString stringWithFormat:@"Bearer %@", token] forHTTPHeaderField:@"Authorization"]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"请求出错:%@", error.localizedDescription); return; } NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if (!httpResponse || httpResponse.statusCode < 200 || httpResponse.statusCode >= 300) { NSLog(@"响应无效或状态码错误:%ld", (long)httpResponse.statusCode); if (data) { NSString *errorMsg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"错误信息:%@", errorMsg); } return; } if (data) { NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"响应内容:%@", responseString); } }]; [task resume]; }];
2. 调用Callable Functions
#import <FirebaseFunctions/FirebaseFunctions.h> // 初始化Functions实例 FIRFunctions *functions = [FIRFunctions functionsWithRegion:@"<你的地区>"]; // 调用函数,可传入参数 [[functions httpsCallableWithName:@"protectedCallableFunction"] callWithParameters:@{@"someData": @"测试数据"} completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) { if (error) { if ([error.domain isEqualToString:FIRFunctionsErrorDomain]) { FIRFunctionsErrorCode code = (FIRFunctionsErrorCode)error.code; NSString *message = error.localizedDescription; id details = error.userInfo[FIRFunctionsErrorDetailsKey]; NSLog(@"Callable函数出错:%ld,%@,详情:%@", (long)code, message, details); } return; } // 解析返回数据 NSDictionary *responseData = result.data; NSString *message = responseData[@"message"]; NSLog(@"后端响应:%@", message); }];
内容的提问来源于stack exchange,提问作者3vangelos
相关产品推荐
相关产品推荐

