目次
認証処理
前提条件
依存関係
ディレクトリ構造と開発環境の設定
データベース設定
スキーマとパーサーをGraphQLサーバーと統合します
モデル
パーサー
サーバ
APIをテストします
登録ユーザーの突然変異
ログイン変異
個々のユーザーのクエリ
要約します
ホームページ ウェブフロントエンド CSSチュートリアル nodejsとgraphqlを使用して独自の認証APIを作成します

nodejsとgraphqlを使用して独自の認証APIを作成します

Apr 02, 2025 am 04:22 AM

nodejsとgraphqlを使用して独自の認証APIを作成します

認証は、GraphQLを新しい開発者にとって最も挑戦的なタスクの1つです。簡単に設定できるORMの選択、安全なトークンとハッシュのパスワードを生成する方法、さらには使用するHTTPライブラリさえも使用する方法など、多くの技術的な考慮事項が関係しています。

この記事では、ローカル認証に焦点を当てています。これはおそらく、最新のWebサイトが認証を処理する最も一般的な方法であり、ユーザーのメールパスワードを要求することで達成されます(Google認証を使用するのではなく)。

さらに、この記事では、Apollo Server 2、JSON Web Tokens(JWT)を使用し、ormを続編してnode.js認証APIを作成します。

認証処理

システムにログインします:

  • 認証は、ユーザーを識別または認証します。
  • 認証されたユーザーがアクセスできるルート(またはアプリケーションの一部)の検証を許可します

このプロセスを実装する手順は次のとおりです。

  1. ユーザーはパスワードと電子メールで登録します。
  2. ユーザーの資格情報はデータベースに保存されます。
  3. 登録が完了すると、ユーザーはログインページにリダイレクトされます。
  4. 認証後、ユーザーは特定のリソースへのアクセスが許可されます。
  5. ユーザーのステータスは、ブラウザストレージメディア(LocalStorage、Cookie、セッションなど)またはJWTに保存されます。

前提条件

より深く入る前に、ここに従う必要があるいくつかのステップがあります。

  • node.js 6以降
  • 糸(推奨)またはNPM
  • GraphQlの遊び場
  • graphqlとnode.jsの基本
  • …知識を求める心!

依存関係

これが長いリストです、始めましょう:

  • Apollo Server :あらゆるタイプのGraphQLクライアントと互換性のあるオープンソースGraphQLサーバー。このプロジェクトでは、Expressはサーバーとして使用しません。代わりに、Apollo Serverの機能を活用してGraphQL APIを公開します。
  • bcryptjs :ユーザーパスワードをデータベースにハッシュしたい。そのため、BCRYPTを使用します。安全な乱数を取得するために、 Web Crypto APIのGetRandomValuesインターフェイスに依存しています。
  • dotenv :dotenvを使用して、.envファイルから環境変数をロードします。
  • JSONWEBTOKEN :ユーザーがログインした後、後続の各リクエストにはJWTが含まれ、ユーザーがトークンを使用して許可されているルート、サービス、およびリソースにアクセスできるようにします。 JsonWebtokenは、ユーザーのIDの検証に使用されるJWTSを生成するために使用されます。
  • Nodemon :ディレクトリの変更が検出されたときにノードアプリケーションを自動的に再起動することにより、ノードベースのアプリケーションの開発に役立つツール。コードが変更されるたびにサーバーをシャットダウンして開始することは望ましくありません。 Nodemonは、毎回アプリケーションの変更をチェックし、サーバーを自動的に再起動します。
  • MySQL2 :node.jsのSQLクライアント。移行を実行できるように、SQLサーバーに接続する必要があります。
  • 後遺症:Sequelizeは、Postgres、MySQL、Mariadb、SQLite、Microsoft SQL Serverで使用される約束ベースのノードORMです。続編を使用して、移行とモデルを自動的に生成します。
  • CLIの後遺症:CLIの後遺症を使用して、後遺症コマンドを実行します。 Yarn add -Global Sequelize-Cliを使用して、端末にグローバルにインストールします。

ディレクトリ構造と開発環境の設定

真新しいプロジェクトを作成しましょう。新しいフォルダーを作成し、その中に次のように作成します。

 <code>yarn init -y</code>
ログイン後にコピー

-yフラグとは、すべてのyarn initの問題に対して[はい]を選択し、デフォルト値を使用することを意味します。

また、Package.jsonファイルをフォルダーに配置する必要があるため、プロジェクトの依存関係をインストールしましょう。

 <code>yarn add apollo-server bcryptjs dotenv jsonwebtoken nodemon sequelize sqlite3</code>
ログイン後にコピー

次に、開発環境にバベルを追加しましょう。

 <code>yarn add babel-cli babel-preset-env babel-preset-stage-0 --dev</code>
ログイン後にコピー

それでは、Babelを構成しましょう。ターミナルでタッチ.babelrcを実行します。これにより、Babel構成ファイルが作成されて開きます。ここでは、以下を追加します。

 <code>{ "presets": ["env", "stage-0"] }</code>
ログイン後にコピー

サーバーがデータを開始して移行した場合、さらに優れています。これを次のように更新することで、これを自動的に行うことができます。

 <code>"scripts": { "migrate": " sequelize db:migrate", "dev": "nodemon src/server --exec babel-node -e js", "start": "node src/server", "test": "echo \"Error: no test specified\" && exit 1" },</code>
ログイン後にコピー

これが現在の完全なPackage.jsonファイルです。

 <code>{ "name": "graphql-auth", "version": "1.0.0", "main": "index.js", "scripts": {  "migrate": " sequelize db:migrate",  "dev": "nodemon src/server --exec babel-node -e js",  "start": "node src/server",  "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": {  "apollo-server": "^2.17.0",  "bcryptjs": "^2.4.3",  "dotenv": "^8.2.0",  "jsonwebtoken": "^8.5.1",  "nodemon": "^2.0.4",  "sequelize": "^6.3.5",  "sqlite3": "^5.0.0" }, "devDependencies": {  "babel-cli": "^6.26.0",  "babel-preset-env": "^1.7.0",  "babel-preset-stage-0": "^6.24.1" } }</code>
ログイン後にコピー

開発環境が設定されたので、データベースに移動しましょう。そこに物事を保存します。

データベース設定

MySQLをデータベースとして使用し、リレーショナルマッピングにORMの後遺症を使用します。 Initの後遺症を実行します(以前にグローバルにインストールしたことがあると仮定します)。このコマンドは、 /config /モデルと /移行の3つのフォルダーを作成する必要があります。現時点では、プロジェクトディレクトリ構造が形成されています。

データベースを構成しましょう。まず、プロジェクトルートディレクトリに.ENVファイルを作成し、以下を貼り付けます。

 <code>NODE_ENV=development DB_HOST=localhost DB_USERNAME= DB_PASSWORD= DB_NAME=</code>
ログイン後にコピー

次に、作成したばかりの /configフォルダーに移動し、そのconfig.jsonファイルをconfig.jsに変更します。次に、次のコードを入れます。

 <code>require('dotenv').config() const dbDetails = { username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, host: process.env.DB_HOST, dialect: 'mysql' } module.exports = { development: dbDetails, production: dbDetails }</code>
ログイン後にコピー

ここでは、.envファイルで設定したデータベースの詳細を読み取ります。 Process.ENVは、システム環境の現在の状態を表すためにノードによって注入されたグローバル変数です。

適切なデータでデータベースの詳細を更新しましょう。 SQLデータベースを開き、GraphQL_Authという名前のテーブルを作成します。 LaRagonをローカルサーバーとして使用し、PHPMyAdminを使用してデータベーステーブルを管理しています。

何を使用しても、最新情報を使用して.ENVファイルを更新する必要があります。

 <code>NODE_ENV=development DB_HOST=localhost DB_USERNAME=graphql_auth DB_PASSWORD= DB_NAME=</code>
ログイン後にコピー

続編を設定しましょう。プロジェクトのルートディレクトリに.sequelizercファイルを作成し、以下を貼り付けます。

 <code>const path = require('path') module.exports = { config: path.resolve('config', 'config.js') }</code>
ログイン後にコピー

次に、構成をモデルに統合しましょう。 /モデルフォルダーのindex.jsに移動し、config変数を編集します。

 <code>const config = require(__dirname '/../../config/config.js')[env]</code>
ログイン後にコピー

最後に、モデルを書きましょう。このプロジェクトには、ユーザーモデルが必要です。続編を使用してモデルを自動的に生成しましょう。ターミナルで実行するために実行する必要があるものは次のとおりです。

 <code>sequelize model:generate --name User --attributes username:string,email:string,password:string</code>
ログイン後にコピー

作成したモデルを編集しましょう。 user.js in /modelsフォルダーに移動し、次のことを貼り付けます。

 <code>'use strict'; module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', {  username: {   type: DataTypes.STRING,  },  email: {   type: DataTypes.STRING,   },  password: {   type: DataTypes.STRING,  } }, {}); return User; };</code>
ログイン後にコピー

ここでは、ユーザー名、電子メール、パスワードのプロパティとフィールドを作成します。移行を実行して、スキーマの変更を追跡しましょう。

 <code>yarn migrate</code>
ログイン後にコピー

それでは、パターンとパーサーを書きましょう。

スキーマとパーサーをGraphQLサーバーと統合します

このセクションでは、パターンを定義し、パーサー関数を書き込み、サーバーに公開します。

モデル

SRCフォルダーで、 /schemaという名前の新しいフォルダーを作成し、schema.jsという名前のファイルを作成します。次のコードを貼り付けます。

 <code>const { gql } = require('apollo-server') const typeDefs = gql` type User {  id: Int!  username: String  email: String! } type AuthPayload {  token: String!  user: User! } type Query {  user(id: Int!): User  allUsers: [User!]!  me: User } type Mutation {  registerUser(username: String, email: String!, password: String!): AuthPayload!  login (email: String!, password: String!): AuthPayload! } ` module.exports = typeDefs</code>
ログイン後にコピー

ここでは、Apollo-ServerからGraphQL-TAGをインポートします。 Apollo Serverは、GQLでパターンをラップする必要があります。

パーサー

SRCフォルダーで、 /resolversという名前の新しいフォルダーを作成し、Resolver.jsという名前のファイルを作成します。次のコードを貼り付けます。

 <code>const bcrypt = require('bcryptjs') const jsonwebtoken = require('jsonwebtoken') const models = require('../models') require('dotenv').config() const resolvers = {  Query: {   async me(_, args, { user }) {    if(!user) throw new Error('You are not authenticated')    return await models.User.findByPk(user.id)   },   async user(root, { id }, { user }) {    try {     if(!user) throw new Error('You are not authenticated!')     return models.User.findByPk(id)    } catch (error) {     throw new Error(error.message)    }   },   async allUsers(root, args, { user }) {    try {     if (!user) throw new Error('You are not authenticated!')     return models.User.findAll()    } catch (error) {     throw new Error(error.message)    }   }  },  Mutation: {   async registerUser(root, { username, email, password }) {    try {     const user = await models.User.create({      username,      email,      password: await bcrypt.hash(password, 10)     })     const token = jsonwebtoken.sign(      { id: user.id, email: user.email},      process.env.JWT_SECRET,      { expiresIn: '1y' }     )     return {      token, id: user.id, username: user.username, email: user.email, message: "Authentication succesfull"     }    } catch (error) {     throw new Error(error.message)    }   },   async login(_, { email, password }) {    try {     const user = await models.User.findOne({ where: { email }})     if (!user) {      throw new Error('No user with that email')     }     const isValid = await bcrypt.compare(password, user.password)     if (!isValid) {      throw new Error('Incorrect password')     }     // return jwt     const token = jsonwebtoken.sign(      { id: user.id, email: user.email},      process.env.JWT_SECRET,      { expiresIn: '1d'}     )     return {      token, user     }   } catch (error) {    throw new Error(error.message)   }  } }, } module.exports = resolvers</code>
ログイン後にコピー

たくさんのコードがあります、そこで何が起こっているのか見てみましょう。

まず、モデルであるBcrypt、およびJSonWebtokenをインポートし、環境変数を初期化します。

次はパーサー関数です。クエリパーサーには、3つの関数(私、ユーザー、およびオルサー)があります。

  • MEクエリは、現在ログインしているユーザーの詳細情報を取得します。ユーザーオブジェクトをコンテキストパラメーターとして受け入れます。コンテキストは、クエリに記載されているIDを介してユーザーデータをロードするために使用されるデータベースへのアクセスを提供するために使用されます。
  • ユーザークエリは、ユーザーのIDに基づいてユーザーの詳細情報を取得します。 IDをコンテキストパラメーターとユーザーオブジェクトとして受け入れます。
  • Alluserクエリは、すべてのユーザーの詳細を返します。

ユーザーステータスがログインされている場合、ユーザーはオブジェクトになります。ユーザーがログインしていない場合、ユーザーはnullになります。このユーザーを突然変異して作成します。

Mutation Parserには、2つの機能(RegisterUserとLoglogluser)があります。

  • RegisterUserは、ユーザーのユーザー名、電子メール、およびパスワードを受け入れ、これらのフィールドを使用してデータベースに新しい行を作成します。 bcryptjsパッケージを使用して、bcrypt.hash(パスワード、10)を使用してユーザーのパスワードをハッシュすることに注意する必要があります。 jsonwebtoken.sign与えられたペイロードをJSON Webトークン文字列(この場合はユーザーIDと電子メール)に同期して署名します。最後に、RegisterUserが成功した場合はJWT文字列とユーザープロファイルを返します。エラーが発生した場合、エラーメッセージが返されます。
  • ログインは電子メールとパスワードを受け入れ、これらの詳細が提供された詳細と一致するかどうかを確認します。まず、ユーザーデータベースのどこかに電子メール値が既に存在するかどうかを確認します。
 <code>models.User.findOne({ where: { email }}) if (!user) { throw new Error('No user with that email') }</code>
ログイン後にコピー

次に、bcryptのbcrypt.compareメソッドを使用して、パスワードが一致するかどうかを確認します。

 <code>const isValid = await bcrypt.compare(password, user.password) if (!isValid) { throw new Error('Incorrect password') }</code>
ログイン後にコピー

次に、以前にRegisterUserでやったように、JSONWeBtoken.Signを使用してJWT文字列を生成します。ログイン変異は、トークンとユーザーオブジェクトを返します。

次に、jwt_secretを.envファイルに追加しましょう。

 <code>JWT_SECRET=一个非常长的秘密</code>
ログイン後にコピー

サーバ

最後に、それはサーバーです!プロジェクトのルートフォルダーにserver.jsを作成し、以下を貼り付けます。

 <code>const { ApolloServer } = require('apollo-server') const jwt =  require('jsonwebtoken') const typeDefs = require('./schema/schema') const resolvers = require('./resolvers/resolvers') require('dotenv').config() const { JWT_SECRET, PORT } = process.env const getUser = token => { try {  if (token) {   return jwt.verify(token, JWT_SECRET)  }  return null } catch (error) {  return null } } const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => {  const token = req.get('Authorization') || ''  return { user: getUser(token.replace('Bearer', ''))} }, introspection: true, playground: true }) server.listen({ port: process.env.PORT || 4000 }).then(({ url }) => { console.log(`? Server ready at ${url}`); });</code>
ログイン後にコピー

ここでは、スキーマ、リゾルバー、JWTをインポートし、環境変数を初期化します。最初に、検証を使用してJWTトークンを確認します。 JWT.Verifyは、トークンとJWTキーをパラメーターとして受け入れます。

次に、TypedefsとResolversを受け入れるApolloserverインスタンスを使用してサーバーを作成します。

サーバーがあります!ターミナルでYarn Devを実行することから始めましょう。

APIをテストします

次に、GraphQL Playgroundを使用してGraphQL APIをテストしましょう。 IDを介して、個々のユーザーを含むすべてのユーザーを登録、ログイン、および表示できるはずです。

まず、GraphQL Playgroundアプリを開くか、ブラウザにLocalHost:// 4000を開き、アクセスします。

登録ユーザーの突然変異

<code>mutation { registerUser(username: "Wizzy", email: "[email protected]", password: "wizzyekpot" ){  token } }</code>
ログイン後にコピー

このような結果を得る必要があります:

 <code>{ "data": {  "registerUser": {   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzAwLCJleHAiOjE2MzA3OTc5MDB9.gmeynGR9Zwng8cIJR75Qrob9bovnRQT242n6vfBt5PY"  } } }</code>
ログイン後にコピー

ログイン変異

次に、作成したばかりのユーザーの詳細でログインしましょう。

 <code>mutation { login(email:"[email protected]" password:"wizzyekpot"){  token } }</code>
ログイン後にコピー

このような結果を得る必要があります:

 <code>{ "data": {  "login": {   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc"  } } }</code>
ログイン後にコピー

素晴らしい!

個々のユーザーのクエリ

単一のユーザーを照会するには、ユーザートークンを承認ヘッダーとして渡す必要があります。 HTTPヘッダータブに移動します。

...そして、このコンテンツを貼り付けます:

 <code>{ "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTUsImVtYWlsIjoiZWtwb3RAZ21haWwuY29tIiwiaWF0IjoxNTk5MjQwMzcwLCJleHAiOjE1OTkzMjY3NzB9.PDiBKyq58nWxlgTOQYzbtKJ-HkzxemVppLA5nBdm4nc" }</code>
ログイン後にコピー

これがクエリです:

 <code>query myself{ me {  id  email  username } }</code>
ログイン後にコピー

このような結果を得る必要があります:

 <code>{ "data": {  "me": {   "id": 15,   "email": "[email protected]",   "username": "Wizzy"  } } }</code>
ログイン後にコピー

素晴らしい!それでは、IDでユーザーを取得しましょう。

 <code>query singleUser{ user(id:15){  id  email  username } }</code>
ログイン後にコピー

これがすべてのユーザーを取得するためのクエリです:

 <code>{ allUsers{  id  username  email } }</code>
ログイン後にコピー

要約します

認証は、認証が必要なWebサイトを構築する際の最も難しいタスクの1つです。 GraphQLを使用すると、1つのエンドポイントのみを使用して完全な認証APIを構築できます。 SQLデータベースとの関係を簡単に作成できるため、ORMを続編するため、モデルについて心配する必要はほとんどありません。また、HTTPサーバーライブラリ(Expressなど)は必要ありませんが、Apollo GraphQLをミドルウェアとして使用する必要はありません。 Apollo Server 2により、独自のライブラリに依存しないGraphQLサーバーを作成できるようになりました。

GitHubのこのチュートリアルについては、ソースコードを確認してください。

以上がnodejsとgraphqlを使用して独自の認証APIを作成しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Googleフォント変数フォント Googleフォント変数フォント Apr 09, 2025 am 10:42 AM

Google Fontsが新しいデザイン(ツイート)を展開したようです。最後の大きな再設計と比較して、これははるかに反復的です。違いをほとんど伝えることができません

HTML、CSS、JavaScriptを使用してアニメーションカウントダウンタイマーを作成する方法 HTML、CSS、JavaScriptを使用してアニメーションカウントダウンタイマーを作成する方法 Apr 11, 2025 am 11:29 AM

プロジェクトにカウントダウンタイマーが必要だったことはありますか?そのようなことのために、プラグインに手を伸ばすのは自然なことかもしれませんが、実際にはもっとたくさんあります

HTMLデータ属性ガイド HTMLデータ属性ガイド Apr 11, 2025 am 11:50 AM

HTML、CSS、およびJavaScriptのデータ属性について知りたいと思っていたことはすべて。

SASSをより速くするための概念の証明 SASSをより速くするための概念の証明 Apr 16, 2025 am 10:38 AM

新しいプロジェクトの開始時に、SASSコンピレーションは瞬く間に起こります。これは、特にbrowsersyncとペアになっている場合は素晴らしい気分です。

SVGでタータンパターンを生成する静的サイトを作成する方法 SVGでタータンパターンを生成する静的サイトを作成する方法 Apr 09, 2025 am 11:29 AM

タータンは、スコットランド、特にファッショナブルなキルトに通常関連する模様のある布です。 Tartanify.comでは、5,000を超えるTartanを集めました

WordPressテーマでVueコンポーネントを構築する方法 WordPressテーマでVueコンポーネントを構築する方法 Apr 11, 2025 am 11:03 AM

インラインテンプレートディレクティブにより、既存のWordPressマークアップに対する進行性の強化として、リッチVUEコンポーネントを構築できます。

PHPはテンプレートのA-OKです PHPはテンプレートのA-OKです Apr 11, 2025 am 11:04 AM

PHPテンプレートは、多くの場合、サブパーコードを促進するために悪いラップを取得しますが、そうである必要はありません。 PHPプロジェクトが基本を実施する方法を見てみましょう

SASSをプログラミングして、アクセス可能な色の組み合わせを作成します SASSをプログラミングして、アクセス可能な色の組み合わせを作成します Apr 09, 2025 am 11:30 AM

私たちは常にWebをよりアクセスしやすくしたいと考えています。色のコントラストは単なる数学なので、SASSはデザイナーが見逃したかもしれないエッジケースをカバーするのに役立ちます。

See all articles