Node로 인증 코드 생성기를 만듭니다.회사 명

검증 코드는 not accessible로 어떤 상황에서는 심지어 효과가 없지만 우리 자신의 검증 코드를 생성함으로써 우리는 많은 것을 배울 수 있습니다!
본문의 원본 코드를 찾으려면 healeycodes/captcha-api 를 방문하십시오.

스팸 솔루션


고객이 로봇 스팸메일 솔루션을 필요로 한다고 상상해 봅시다.그들은 그림과 텍스트 문자열을 필요로 한다.너는 네가 우울하게 해결하지 못한 종잡을 수 없는 자모와 숫자를 떠올릴 것이다.그럼에도 불구하고, 너는 이 임무에 동의한다.

이 고객은 일련의 사이트를 가지고 있다.서로 다른 곳에는 서로 다른 크기의 검증 코드가 필요하다.그것들은 너비와 높이를 제공할 것이다.이것은 우리 API의 규범을 설명한다.
JavaScript는 이미지를 생성하는 데 매우 적합합니다Canvas API.나는 항상 내가 곤경에 빠졌을 때, 그것은 많은 Stackoverflow 내용과 함께 편리하게 사용할 수 있다는 것을 발견한다.
우리는 브라우저에서 인증 코드를 만들고 싶지 않다. 왜냐하면 우리가 막으려는 로봇은 원본 코드를 검사하고 메모리의 값을 찾으며 각종 까다로운 정책을 시도할 수 있기 때문이다.

하나의 노드.js 서비스


백엔드로 이동해서 필요에 따라 호출할 수 있는 서비스로 이동합시다.웹 API 없이 웹 API에 액세스하는 문제를 이미 node-canvas 또는 npm i canvas 로 해결한 사람이 있습니다.

[canvas] is an implementation of the Web Canvas API and implements that API as closely as possible.


우리는 매번 무작위 텍스트를 생성해야 한다.우리들은 두 개의 함수를 써서 우리를 돕는다.우리의 API에 대해 우리는 논리를 하나의 일을 하는 함수로 분해하여 최종 결과가 추리와 유지보수가 쉽도록 할 것이다.
/* captcha.js */

// We'll need this later
const { createCanvas } = require("canvas");

// https://gist.github.com/wesbos/1bb53baf84f6f58080548867290ac2b5
const alternateCapitals = str =>
  [...str].map((char, i) => char[`to${i % 2 ? "Upper" : "Lower"}Case`]()).join("");

// Get a random string of alphanumeric characters
const randomText = () =>
  alternateCapitals(
    Math.random()
      .toString(36)
      .substring(2, 8)
  );
캔버스 안의 텍스트를 자동으로 축소할 수 없기 때문에 (브라우저에서 우는 것처럼) 우리도 약간의 보조 기능이 필요하다.인증 코드의 길이와 텍스트가 이미지에 있는 위치를 확인하려면 테스트를 해야 할 수도 있습니다.다음은 내가 전에 준비한 변수들이다.
const FONTBASE = 200;
const FONTSIZE = 35;

// Get a font size relative to base size and canvas width
const relativeFont = width => {
  const ratio = FONTSIZE / FONTBASE;
  const size = width * ratio;
  return `${size}px serif`;
};
이렇게 하면 텍스트를 축소할 수 있다. 캔버스의 비율이 변하지 않는다면 우리는 비슷한 그림을 볼 수 있다.
본고에서 우리는 텍스트를 회전하고 싶지만 로봇에게 숨기기 위해 텍스트를 왜곡할 수 있는 방법이 많다. 나는 네가 무엇을 생각해 낼 수 있는지 보고 싶다.
캔버스를 회전할 때 우리가 전달하는 값은 radians 이기 때문에 우리는 무작위 곱하기 Math.PI / 180 를 해야 한다.
// Get a float between min and max
const arbitraryRandom = (min, max) => Math.random() * (max - min) + min;

// Get a rotation between -degrees and degrees converted to radians
const randomRotation = (degrees = 15) => (arbitraryRandom(-degrees, degrees) * Math.PI) / 180;
나는 더 이상 조수 기능이 없다고 보증한다.우리는 이제 진정한 토론을 시작해야 한다.논리는 두 가지 기능으로 나뉜다.configureText 캔버스 대상을 가져와 무작위 텍스트를 추가하고 가운데에 놓는다.generate 폭과 높이를 취하다(우리가 제시한 규격을 기억하십니까?)PNG 이미지Data URL의 인증 코드를 반환합니다.

Data URLs, URLs prefixed with the data: scheme, allow content creators to embed small files inline in documents.


// Configure captcha text
const configureText = (ctx, width, height) => {
  ctx.font = relativeFont(width);
  ctx.textBaseline = "middle";
  ctx.textAlign = "center";
  const text = randomText();
  ctx.fillText(text, width / 2, height / 2);
  return text;
};

// Get a PNG dataURL of a captcha image
const generate = (width, height) => {
  const canvas = createCanvas(width, height);
  const ctx = canvas.getContext("2d");
  ctx.rotate(randomRotation());
  const text = configureText(ctx, width, height);
  return {
    image: canvas.toDataURL(),
    text: text
  };
};
우리는 generate 이외의 모든 함수를 다른 곳에서 사용하지 말아야 할 사유 함수로 간주할 수 있기 때문에 이 함수만 내보낼 수 있다.
module.exports = generate;

Express에서 제공하는 API


지금까지 우리는 이미지 생성 논리를 포함하는 파일 captcha.js 을 가지고 있다.이 기능을 다른 사람이 호출할 수 있도록 HTTP API를 통해 서비스를 제공합니다.Express는 이러한 작업 중 가장 많은 커뮤니티 지원을 받았습니다.
저희가 진행할 노선은 다음과 같습니다.
  • /test/:width?/:height?/
  • 수동 테스트에 사용할 이미지 레이블을 가져옵니다.
  • /captcha/:width?/:height?/
  • 올바른 인증 코드 객체를 가져오는 데 사용됩니다.
  • 라우팅의 물음표는 URL 매개 변수를 선택할 수 있는 빠른 구문입니다.이것은 클라이언트가 제공하지 않거나, 첫 번째 또는 동시에 제공할 수 있다는 것을 의미한다.우리는 정수가 값으로 전달되는지 검증할 것입니다. (canvas 필요) 그렇지 않으면 합리적인 기본값을 사용합니다.
    Express 응용 프로그램 전문:
    /* app.js */
    
    const captcha = require("./captcha");
    const express = require("express");
    const app = express();
    
    // Human checkable test path, returns image for browser
    app.get("/test/:width?/:height?/", (req, res) => {
      const width = parseInt(req.params.width) || 200;
      const height = parseInt(req.params.height) || 100;
      const { image } = captcha(width, height);
      res.send(`<img class="generated-captcha" src="${image}">`);
    });
    
    // Captcha generation, returns PNG data URL and validation text
    app.get("/captcha/:width?/:height?/", (req, res) => {
      const width = parseInt(req.params.width) || 200;
      const height = parseInt(req.params.height) || 100;
      const { image, text } = captcha(width, height);
      res.send({ image, text });
    });
    
    module.exports = app;
    
    이 Express 응용 프로그램이 내보내졌으므로 테스트할 수 있습니다.우리의 API는 이 점에서 기능적이다.우리가 해야 할 일은 다음과 같은 문서 처리 서비스를 제공하는 것이다.
    /* server.js */
    
    const app = require("./app");
    const port = process.env.PORT || 3000;
    
    app.listen(port, () => console.log(`captcha-api listening on ${port}!`));
    
    네비게이션 http://localhost:3000/test 은 우리에게 기본적인 인증 코드를 제공할 것입니다.생략하면 브라우저에 bodyhtml 태그가 추가됩니다.

    유효한 데이터 URL


    테스트를 쓸 때가 되었지만, 우선 당신의 것을 내려놓으세요unwieldy regular expressions.한 가지library가 이미 이 문제를 해결했다.valid-data-url 통조림에 적힌 대로 완전히 만든다.
    나는 제스트를 나의 테스트 주자로 사용하는 것을 좋아한다.그것이 줄곧 나에게 효과가 있는 것 외에 다른 원인은 없다. 그것이 작용하지 않을 때, 나는 답을 찾을 수 있다.내 설정은 다음과 같이 scripts 에서 package.json 키를 설정합니다.
      "scripts": {
        "test": "jest"
      }
    
    이렇게 하면 입력할 수 있습니다 npm test.Jest는 모든 테스트를 찾아 실행합니다.
    우리 프로그램의 테스트 파일은 Express 응용 프로그램 대상을 가져오고 supertest 를 사용하여 HTTP 요청을 시뮬레이션합니다.우리는 비동기/대기 문법을 사용하여 리셋을 줄인다.
    /* app.test.js */
    
    const request = require("supertest");
    const assert = require("assert");
    const validDataURL = require("valid-data-url");
    const app = require("../app");
    
    describe("captcha", () => {
      describe("testing captcha default", () => {
        it("should respond with a valid data URL", async () => {
          const image = await request(app)
            .get("/captcha")
            .expect(200)
            .then(res => res.body.image);
          assert(validDataURL(image));
        });
      });
    
      describe("testing captcha default with custom params", () => {
        it("should respond with a valid data URL", async () => {
          const image = await request(app)
            .get("/captcha/300/150")
            .expect(200)
            .then(res => res.body.image);
          assert(validDataURL(image));
        });
      });
    });
    
    이 응용 프로그램의 크기를 고려하여 나는 그것을 두 개의 통합 테스트에 남기는 것에 만족한다.

    GitHub 워크플로우와의 지속적인 통합


    표준 npm 테스트 명령 npm test 을 사용하여 저장소를 구성하기 때문에 몇 번 클릭하면 GitHub 워크플로우를 만들 수 있습니다.이렇게 하면 우리의 응용 프로그램은 코드를 전송할 때마다 구축하고 테스트할 것이다.

    지금 저희가 귀여운 휘장을 가지고 자랑합니다!
    150여 명이 가입해 저의 newsletter 프로그램과 개인 성장!
    나는 트위터에 과학 기술을 이야기했다.

    좋은 웹페이지 즐겨찾기