You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:30:00