学习期刊 - Digileger项目日志
#javascript #网络开发人员 #react #开发日志

我最近开始使用Twitter,并遇到了#learninpublic的这一趋势。我看到很多人记录他们的日常进度。看到其他开发人员在高技能方面相互支持是令人鼓舞的。它给了我通过博客记录我的学习的想法。所以,我在这里。

learn in public

几个月前,我开始学习反应和逆风。当时,我还在考虑建立一个申请,以跟踪我的费用和预算。自然而然地,我想到的是,练习我的学习将是一个很棒的项目。所以我开始了。

我计划构建一个CRUD应用程序,可以在其中输入交易的详细信息,并且可以处理这些应用程序,以提供每月分析和累积数据。

这是我制作的,Digiledger,交易管理和费用跟踪应用程序。

这是我到目前为止集成的基本功能。

  • 记录交易
  • 交易过滤
  • 费用和收入分析

这是链接:
实时网站:https://digiledger.vercel.app/
前端存储库:https://github.com/AnshumanMahato/Digiledger-Frontend
后端存储库:https://github.com/AnshumanMahato/DigiLedger-Backend

我有计划使用更多功能扩展该项目。但这仅此而已。本文更多地是关于我在构建这个项目时学到的东西。

建立项目以学习知识,并分享您的学习以巩固它们。

研究东西是学习任何东西的最佳方法。毫无疑问。除了学习外,它还建立了与之合作的信心。这就是这个项目对我的帮助。我发现反应速度更快,并获得了一些有趣的见解。

这是我学到的主要内容:

首先还是后端?

在我以前的项目中,我主要从事后端工作。我从来没有遇到任何问题,因为我有必须工作的准则。我得到了终点,他们的要求和他们的回答列表。所以这从来都不是问题。

这是我第一次开始从头开始构建所有内容。作为一个后端家伙,我首先跳了起来。而且非常麻烦。我已经弄清楚了终点。困难的是找出请求和响应结构。

frontend or backend

随着后端的工作变得累人,所以我切换到了前端。那时事情变得很清楚。知道我们如何呈现数据使我们对收到和发送的内容有清晰的了解。

我与一些开发人员谈到了他们的工作流程。一些人从设计和前端部分开始,使用模拟API。准备好基本结构后,它们移至后端。然后根据需要继续来回切换。其他人说他们先做了后端,然后整合了前端。

起初,我认为这一定是“ ”的东西。但是一旦思考,我终于明白了。首先不是前端或后端。它的计划需要先完成。

计划设计,模型,体系结构等,并在一开始对它们进行记录对于开发过程至关重要。它们为应用程序提供了边界。它简化了应用程序的范围。

我也意识到我的设计技巧不是很好。我需要做一些工作。ð

使用效应的工作

在文章和教程中,我对使用效应的最初理解是,其中的函数首先执行,然后基于依赖项数组来调用。我以为这一切都是顺序发生的。

让我们看看以下示例。

import "./styles.css";
import { useEffect, useRef } from "react";

export default function App() {
  const testArr = useRef();

  useEffect(() => {
    testArr.current = ["kratos", "atreus", "mimir", "sindri", "brok"];
  }, []);

  return (
    <div className="App">
      {testArr.current.map((el) => (
        <p>{el.toUpperCase()}</p>
      ))}
    </div>
  );
}

如果我根据自己的最初理解,这就是它的执行方式。首先,声明testarr,然后使用使用效率执行,然后渲染组件。

和男孩,我错了。控制台向我发送了问候“无法阅读未定义的属性(阅读'Map')。

我做了很多思考并尝试了不同的解决方案,但没有任何效果。但是后来令我震惊。所有文章和教程始终将函数称为使用效率回调。我终于了解发生了什么。首先,我们声明了Testarr最初未定义。然后使用效法执行,将回调的上下文对回调队列。然后渲染组件。此后,当执行堆栈变为空时,从回调队列中选出回调并执行。然后,根据价值变化重新渲染组件。

所以testArr = useRef([])解决了问题。起初,这是一个尤里卡(Eureka)的时刻,但后来我感到愚蠢的是没有彻底浏览资源。
我从所有这些中学到的是对使用效应的良好理解,以及为什么要对国家和参考文献进行适当的初始化至关重要。

在跨站点的情况下与httponly cookie合作

authentication

我正在使用JWT令牌进行身份验证。将其存储在本地存储中,使其容易受到XSS(跨站点脚本)攻击的攻击,因此我正在使用Httponly Cookie。概念是,一旦我们从主机中收到HTTPonly cookie,只要浏览器拥有它,浏览器就会将其发送给该主机。由于客户端脚本无法访问httponly cookie,因此它可以防止XSS攻击。

我在以前的大多数项目中都使用了这种策略。它总是很好。但是这一次,它无效。浏览器正在接收曲奇,但没有将其发送回。浏览器控制台或服务器上都没有错误。我搜索了“浏览器不将cookie发送到服务器”,但什么都没有。

尽管我没有发现任何解决方案,但仍提到了CORS政策,原始标题,Samesite和CSRF对基于Cookie的身份验证的攻击。我的前端和后端是独立的应用程序。他们在不同的港口工作,所以这是一个跨点的情况。因此,即使我对此不了解,我也有一个预感,这可能是问题(我是对的)。

我们知道,我们将HTTPonly Cookie发送到每个请求的主机。默认情况下,仅当客户端和服务器在同一域上时才发生。如果我将前端作为静态文件服务,那将有效。或者,如果我像以前的项目一样使用了服务器端渲染。但是,我们必须针对跨站点请求明确指定此。在Axios中,我们设置了withCredentials配置字段。

    axios.get(BASE_URL + '/todos', { withCredentials: true });
// default for all requests
    axios.defaults.withCredentials = true
// only with a group of requests
    const instance = axios.create({
        withCredentials: true,
        baseURL: BASE_URL
    })
    instance.get('/todos')

在Fetch API中,我们使用credentials Config Field。它需要其中之一
三个值,

  • 如果您只想在请求URL与调用脚本相同的原点时发送凭据,请添加credentials: 'same-origin'
  • 使浏览器发送带有凭据同时包含凭证和交叉呼叫的凭据的请求,请添加credentials: 'include'
  • 为了确保浏览器在请求中不包含凭据,请使用credentials: 'omit'
fetch("https://example.com", {
  credentials: "include",
});

我们将Access-Control-Allow-Credentials响应标头设置为true在我们的服务器上。

,但即使在此之后,它也无效。经过一番研究,我发现这是由于保护CSRF攻击所致。

data breach

CSRF代表跨站点资源伪造。让我们以一个例子理解这一点。假设一个系统位于www.front.com处的前端,而后端位于www.back.com。我们打算做的是将API称为from www.front.comwww.back.com。但是,假设用户访问了骗局网站www.trustmebiro.com。它默默地对www.back.com进行了一些API调用。在允许跨站点的情况下,这可以正常工作,因为我们只需要令牌cookie进行身份验证。因此,我们为意外客户提供未经授权的访问权限,并容易受到数据泄露的影响。

可以在cookie选项中设置SameSite属性,以防止CSRF攻击。它可以采用任何值,

  • Strict-您的cookie只能在第一方上下文中发送。用用户术语,浏览器仅在cookie网站与当前在浏览器的URL栏中显示的站点匹配的网站时发送cookie。但是,在遵循指向您网站的链接时,从另一个网站或通过朋友的电子邮件说,浏览器不会在该初始请求下发送cookie。当您拥有与功能有关的cookie时,这始终是初始导航的后面,例如更改密码或进行购买,但这太过限制了。
  • Lax-如果您的读者遵循链接到该站点,他们希望发送cookie,以便可以应用他们的偏好。这就是SameSite=Lax的来源,允许浏览器以这些顶级导航发送cookie。
  • None-使用此选项,浏览器将随着所有请求发送cookie,而不论原点如何。但是这样,cookie必须具有Secure属性。它确保我们仅通过HTTPS连接发送cookie。另外,我们需要在我们的CORS政策中包括The Access-Control-Allow-Origin

最后一个选择是我要做的。因此,毕竟,我终于使自己的应用程序按照预期的方式工作。这很乏味。但是我学到了很多有关互联网攻击,CORS政策,服务器配置和网络的知识。

取消组件上的请求

request response cycle

之后,该应用程序的最低功能完成了。所以我部署了它。我使用免费服务来部署我的应用程序,因此性能很慢。它使我思考了连接缓慢的用户。

我的应用程序中没有加载屏幕。因此,没有迹象表明发生了什么事。因此我做了一个。这也让我思考,如果用户在请求持续时尝试导航怎么办?到响应来了,他们将在另一个页面上。它将没有用。因此,我开始寻找在组件卸载时取消悬而未决请求的方法。我必须了解AbortController

根据MDN,AbortController接口代表一个控制器对象,允许您在需要时按照或多个Web请求中止。它具有属性signal和一个实例方法abort()

这是我们将其与Axios一起使用的方式。

const controller = new AbortController(); 
axios
    .get('/foo/bar', { signal: controller.signal })
    .then(function(response) { 
         //... 
    }); 

// cancel the request 
controller.abort();

尽管这看起来很简单,但我面临着将其与React集成的困难。到目前为止,我已经弄清楚了如何为我们在使用效率回调中提出的请求实施它。这就是我们的方式。

import axios from "axios";
import {useEffect} from "react";

function Component() {
useEffect(()=>{
    const controller  = new AbortController();
    (async()=>{
        const response = await axios.get('www.example.com',{
            signal: controller.signal,
        })
        //further manipulations
    })();

    return ()=>controller.abort();
});

return (<div>
        {/*Component body*/}
    </div>)
}

我仍然需要弄清楚如何根据用户操作(例如登录或交易创建)触发的请求。我正在研究它。如果您有任何建议,请在评论中告诉我。

好吧,这就是伙计们!

这就是我迄今为止通过这个项目收集的一切。正如我之前说的那样,这是一次很棒的学习经历。我需要弄清楚更多的东西。我需要在这个项目上做很多工作。但是到目前为止我做的一切都很有趣。

我希望这个博客对您有见地。如果您对任何事情有任何建议或反馈,请评论。或者您也可以在Twitter上与我联系。我的手柄是@AnshumanMahato_

感谢您阅读这篇文章。 ð