SPA - Firebase 和 .Net WebApi 2 身份验证

2023-11-27

我有一个用 AngularJs 编写的单页应用程序(此时框架无关紧要)该应用程序托管在 IIS 中,它由 index.html 和一堆客户端资产组成。

在后端,我有 WebApi 2,它也作为单独的应用程序托管在 IIS 中。

对于客户端身份验证,我使用 Firebase(简单登录)并启用了多个社交网络,例如 Facebook、Twitter 或 Google。

到目前为止,一切都很好。我喜欢使用 firebase 等轻松启用 Twitter 身份验证。

登录社交网络时,我从 firebase 获取 firebaseAuthToken 和提供者 accesstoken。

现在我想使用 firebaseAuthToken 或提供程序访问令牌通过我的 WebApi 进行身份验证。

问题是:在给定条件下使用 WebApi 进行身份验证的最佳方法是什么?

由于我在服务器上部署了复杂的业务逻辑,因此无法选择仅使用 firebase 来存储我的数据并摆脱 Web api。

到目前为止,我的一个愚蠢的想法是将社交提供商访问令牌传递到服务器,针对提供商验证令牌,然后使用 Owin -Katana 颁发安全令牌。

由于缺乏文档、复杂性以及与单页应用程序的集成不良,我没有使用 katana 的内置社交提供商支持。我发现 SPA 的 Visual Studio 模板太 mvc 特定。但这就是我:)


tl;dr - GitHub 上的演示项目

下面的步骤可能看起来很长,但实际上非常简单。我只用了一个小时左右就创建了我的演示项目。


我同意你关于使用 Owin 和 Katana 的观点。我以前经历过这个过程,但这并不是一次很棒的经历。使用 Firebase 就容易多了。

这一切都可以通过 JWT 来完成!

当您通过 Firebase 和任何社交提供商进行身份验证时,您会得到一个 JSON Web 令牌 (JWT) -firebaseAuthToken.

从仪表板获取您的 Firebase 秘密

JWT 的工作方式是我们有一个秘密令牌和一个客户端令牌。客户端令牌是我们登录后收到的 firebaseAuthToken。秘密令牌是在 Firebase 仪表板中为我们生成的。

Firebase JWTs Dashboard

将您的 Firebase Secret 存储在 Web.config 的 appSettings 部分中

我们需要将此密钥存储在 Web.config 中,以便以后更容易访问。

<add key="FirebaseSecret" value="<Firebase-Secret-Token-Goes-Here" />

创建操作过滤器以检查授权标头中的 JWT

我们可以通过在授权标头中传递客户端令牌来验证请求是否有效。在服务器上,我们可以存储从 Firebase 仪表板获取的密钥。当 Web API 检查请求时,我们可以使用 JWT 库对 JWT 进行解码(可从 NuGet 获得)。如果解码成功,那么我们可以检查令牌以确保它没有过期。

public class DecodeJWT: ActionFilterAttribute 
{

    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 
    {
        string firebaseAuthToken = string.Empty;
        if (actionContext.Request.Headers.Authorization != null) {
            firebaseAuthToken = actionContext.Request.Headers.Authorization.Scheme;
        } else {
            throw new HttpException((int) HttpStatusCode.Unauthorized, "Unauthorized");
        }

        string secretKey = WebConfigurationManager.AppSettings["FirebaseSecret"];
        try {
            string jsonPayload = JWT.JsonWebToken.Decode(firebaseAuthToken, secretKey);
            DecodedToken decodedToken = JsonConvert.DeserializeObject < DecodedToken > (jsonPayload);
            // TODO: Check expiry of decoded token
        } catch (JWT.SignatureVerificationException jwtEx) {
            throw new HttpException((int) HttpStatusCode.Unauthorized, "Unauthorized");
        } catch (Exception ex) {
            throw new HttpException((int) HttpStatusCode.Unauthorized, "Unauthorized");
        }

        base.OnActionExecuting(actionContext);
    }

}

创建一个 $http 拦截器,将 firebase AuthToken 添加到每个请求的标头中

在客户端,技巧是每次都必须传递令牌。为了使这更容易,我们需要创建一个$httpInterceptor与 Angular 一起检查firebaseAuthToken on sessionStorage.

.factory('authInterceptor', function ($rootScope, $q, $window) {
    return {
        request: function (config) {
            config.headers = config.headers || {};
            if ($window.sessionStorage.firebaseAuthToken) {
                config.headers.Authorization = $window.sessionStorage.firebaseAuthToken;
            }
            return config;
        },
        response: function (response) {
            if (response.status === 401) {
                // TODO: User is not authed
            }
            return response || $q.when(response);
        }
    };
})

成功登录后将 firebaseAuthToken 设置为 sessionStorage

每当用户登录时,我们可以将该值设置为sessionStorage.

$rootScope.$on('$firebaseSimpleLogin:login',
    function (e, user) {

        // add a cookie for the auth token
        if (user) {
            $window.sessionStorage.firebaseAuthToken = user.firebaseAuthToken;
        }

        cb(e, user);
    });

全局注册 DecodeJWT 过滤器

里面的WebApiConfig.cs通过注册方法,我们可以设置 DecodeJWT 过滤器以应用于所有 ApiController。

config.Filters.Add(new DecodeJWT());

现在,每当我们向 ApiController 发出请求时,除非存在有效的 JWT,否则它都会拒绝该请求。因此,在用户登录后,如果 ApiController 不存在,我们可以将其数据保存到该 ApiController 中。

// globally uses DecodeJWT
public class UsersController: ApiController 
{
    // POST api/users
    public void Post([FromBody] FbUser user) // See GitHub for this Model
    {
        // Save user if we do not already have it
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SPA - Firebase 和 .Net WebApi 2 身份验证 的相关文章

随机推荐

  • Magento - OnePage Checkout - 根据运输方式隐藏付款方式

    我已经问过这个问题Magento 堆栈交换没有任何成功 因此我现在在这里问 我正在使用 Magento Community Edition 1 9 0 1 并已正确创建和注册我的模块 但我似乎无法检测到运输方式 基本上 我想隐藏货到付款 i
  • 如何正确过滤数据表(datatable.select)

    Dim dt As New DataTable Dim da As New SqlDataAdapter s c c Open If Not IsNothing da Then da Fill dt dt Select GroupingID
  • Pandas 将多个数据帧与时间戳索引对齐

    这一直是我过去几天生活中的祸根 我有许多 Pandas Dataframes 其中包含频率不规则的时间序列数据 我尝试将它们对齐到一个数据框中 下面是一些代码 具有代表性的数据帧 df1 df2 and df3 我实际上有 n 5 并且希望
  • 数据路径“”不应具有附加属性(dryRun)

    我在 MAC 中安装了最新的 Angular 6 0 4 当我在终端中输入时 ng new happiness display Schematic input does not validate against the Schema dry
  • 如何使用 IntelliJ 从 Selenium/TestNG java 文件创建可执行 jar 文件?

    我已经在谷歌上搜索了好几天 试图找出如何做到这一点 如果有人之前这样做过 我将非常感谢您的帮助 我在 IntelliJ 中创建了一个自动化测试项目 可以自动执行用户与 Web 应用程序的交互 我想将该自动化测试 使用 Selenium 和
  • Apache Toree 和 Spark Scala 无法在 Jupyter 中运行

    我在 Jupyter 上运行 Scala Spark 时遇到问题 以下是我在 jupyter 中加载 Apache Toree Scala 笔记本时出现的错误消息 root ubuntu 2gb sgp1 01 jupyter notebo
  • 整理 Git 混乱

    我刚刚继承了一个使用 Git 维护的项目 代码一度被部署到 3 个独立的系统上 每个系统都维护自己的去中心化 Git 存储库 3个系统中的每一个都在3个不同的方向上扩展了原始的基础系统 这 3 个系统均未相互同步 一些更改发生在主分支上 其
  • 文本到音素转换器

    我正在寻找一种将文本转换为音素的工具 例如文本到语音软件 我可以编写一个程序 但它不会没有错误并且需要很多时间 所以我的问题是 有没有一个简单的工具可以转换例如 你好 到 HH AH0 L OW1 也许有一些命令行工具 以便我可以捕获标准输
  • 亚马逊商城 API [已关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我期望亚马逊市场网络服务像任何其他网络服务一样简单 但事实并非如此 似乎有一些关于市场产品提要的信息 任何人都可以帮助我如何开始上传新产品 一步一步 因为我是新手 以及更新数量或
  • 使用elasticsearch-dsl的delete方法时版本冲突

    因此 我们在 Django 项目中使用elasticsearch 并且使用elasticsearch dsl python 库 我们在生产中遇到以下错误 ConflictError 409 took 7 timed out false to
  • ASP.Net MVC 中的自我 AJAX 更新部分视图/控制器和复制 div

    我对 MVC 的部分看法如下 div div 在该 div 内有一个表单 它使用 AJAX 调用控制器并返回相同的部分视图 问题是调用视图的结果替换了 div 的内容 而不是整个 div 我最终得到 div div div div 根据我一
  • 真(非伪)随机数生成器。外面有什么? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我正在寻找能够生成真实随机数的经济实惠的解决方案 我已经发现LavaRnd 这是一个密码学上合理的随机数生成器 有人有这个领域的经验和 或了解其他解决方案吗 PS 恕我直言 这个问题
  • API 获取和浏览器崩溃后 Swagger UI 冻结

    我有一个 ASP NET WebAPI 项目 我试图用 Swagger UI 替换旧的 XmlDocumentationProvider 页面 我正在使用webAPI 5 3 1 的 swashbuckle swagger努吉特包 我能够导
  • 如何创建非持久性 EJB 3.1 计时器?

    使用 NetBeans 7 1 GlassFish 3 1 我创建了一个新的 TimerSessionBean Stateless public class NewTimerSessionBean implements NewTimerSe
  • 如何计算孩子的数量?

    我有一个清单 ul li li li li li li ul 我需要 jQuery 来计算列表中的项目数 您可以使用 length 像这样 var count ul li length length告诉选择器找到了多少个匹配项 因此这会计算
  • 更新 mongodb 中的嵌套数组

    我在 mongodb 中有一个文档 其中包含需要更新的 2 级深度嵌套对象数组 如下所示 id 1 items id 2 blocks id 3 txt hello 如果只有一层深数组 我可以使用位置运算符来更新其中的对象 但对于第二层 我
  • Google App Engine 标准环境还是灵活环境?

    我陷入了选择 Google App Engine Standard 和 Google App Engine Standard 之间的抉择 适合现实世界生产的灵活环境 我肯定想使用Java 需要使用Firebase 最新版本 进行身份验证和推
  • 为子字符串搜索建立索引?

    我想在数十亿个字符串中进行常规子字符串搜索 这个要求与一般的全文搜索有点不同 因为我希望查询 ubst 也可以点击 substr Lucene 或 Sphinx 能够做到这一点吗 如果没有 您认为最好的方法是什么 这种情况下的最佳索引结构是
  • iOS 和 Android 共享 HTTP 深度链接?

    我正在尝试通过 URL 通过电子邮件等共享 启动我的本机应用程序 Android 似乎只响应 HTTP 深层链接 URL 例如 http myapp com stuff 并且 iOS 仅响应非 HTTP 自定义深层链接 URL 例如 mya
  • SPA - Firebase 和 .Net WebApi 2 身份验证

    我有一个用 AngularJs 编写的单页应用程序 此时框架无关紧要 该应用程序托管在 IIS 中 它由 index html 和一堆客户端资产组成 在后端 我有 WebApi 2 它也作为单独的应用程序托管在 IIS 中 对于客户端身份验