Project Templates
Social Network
あなたのソーシャルネットワークの認証システム
47 分
はじめに このチュートリアルでは、back4appをバックエンドサービスとして使用して、ソーシャルネットワークwebアプリケーションの包括的な認証システムを実装する方法を学びます。ユーザー登録、ログイン、パスワードリセット、セッション管理の機能を構築します。これは、現代のソーシャルアプリケーションにとって重要な機能です。 back4appは、サーバーインフラを管理することなく、開発者がスケーラブルなアプリケーションを作成できるparse server上に構築されたbackend as a service(baas)プラットフォームです。組み込みのユーザー認証機能により、安全なユーザー管理システムを迅速に実装するのに最適です。 このチュートリアルの終わりまでに、ソーシャルネットワークアプリケーションであるback4gramで使用されているものに似た完全に機能する認証システムを作成します。ユーザー登録の検証、安全なログイン、パスワード回復、アプリケーション全体での永続的なセッションを実装し、ユーザーにシームレスな体験を提供しながら、アカウントを安全に保ちます。 back4gramプロジェクト: 完全なコードを見つける こちら で、 ソーシャルネットワークサンプルプロジェクト をback4appで構築しました。 前提条件 このチュートリアルを完了するには、次のものが必要です back4appアカウント。 back4app com https //www back4app com で無料アカウントにサインアップできます。 back4appプロジェクトのセットアップ。新しいプロジェクトを作成する方法は、私たちの back4appの始め方ガイド https //www back4app com/docs/get started/welcome に従って学ぶことができます。 ローカルマシンにnode jsがインストールされていること。 javascript、react js、およびrestful apiの基本的な知識。 モダンなウェブ開発の概念(コンポーネント、状態管理など)に慣れていること。 ステップ1 – back4appのユーザー管理システムの理解 コードに飛び込む前に、back4appがユーザー管理をどのように扱っているかを理解することが重要です。back4appはparse server上に構築されており、特別な parse user クラスが認証のために特別に設計されています。 parse userクラス back4appの parse user クラスは、ユーザー認証のための特化した機能を持つ標準のparseオブジェクトを拡張しています。いくつかの組み込みフィールドが含まれています ユーザー名 ユーザーの一意の識別子(必須) パスワード ユーザーのパスワード(サインアップに必要ですが、取得可能な形式では保存されません) メール ユーザーのメールアドレス(任意ですが推奨) メール確認済み ユーザーがメールを確認したかどうかを示すブール値 認証データ サードパーティ認証のための認証データ プロフィール写真、バイオ、またはその他のユーザー固有のデータなど、追加のユーザー情報を保存するためにカスタムフィールドを追加することもできます。 セッション管理 ユーザーがログインすると、back4appはユーザーのセッションを識別するセッショントークンを作成します。このトークンは、ユーザーが再度ログインすることなく、後続のリクエストを認証するために使用されます。セッショントークンはparse sdkによって自動的に管理されますが、必要に応じて手動で制御することもできます。 セッションフローの動作は次のとおりです ユーザーが資格情報(ユーザー名/メールアドレスとパスワード)を提供します back4appが資格情報を検証します 有効な場合、back4appがセッショントークンを作成します トークンはローカルに保存されます(通常はlocalstorageまたは同様のメカニズムに) トークンは、ユーザーを認証するためにその後のapiリクエストに含まれます back4gramアプリケーションでこれがどのように実装されているか見てみましょう。parseの初期化コードは通常次のようになります // initialize parse with your back4app credentials parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com/"; back4gramアプリのこの設定により、すべてのコンポーネントがparse sdkにアクセスし、ユーザーがログインすると認証されたリクエストを行うことができます。 セキュリティ機能 back4appはユーザー管理のためにいくつかのセキュリティ機能を提供しています 安全なパスワードストレージ パスワードは平文で保存されることはなく、自動的にハッシュ化され、ソルトが追加されます。 セッション管理 ユーザーセッションはback4appダッシュボードを通じて管理および取り消すことができます。 アクセス制御リスト (acl) 特定のオブジェクトを誰が読み書きできるかを制御できます。 メール確認 back4appはユーザーに確認メールを送信できます。 パスワードリセット 安全なパスワードリセットのための組み込み機能。 基本を理解したので、プロジェクトの設定に進みましょう。 back4gramプロジェクト: こちら で、 ソーシャルネットワークのサンプルプロジェクト の完全なコードを見つけてください。back4appで構築されています。 ステップ2 – プロジェクトの設定 back4appを使用した認証の実装方法を示すために、back4gramソーシャルネットワークアプリケーションの簡略版を作成します。 新しいreactアプリケーションの作成 まず、新しいreactアプリケーションを作成しましょう。ターミナルを開いて、次のコマンドを実行します npx create react app social network auth cd social network auth 必要なパッケージのインストール 次に、必要なパッケージをインストールします npm install parse react router dom @chakra ui/react @emotion/react @emotion/styled framer motion これらのパッケージは次の機能を提供します parse back4appのためのjavascript sdk react router dom ページルーティングのため @chakra ui/react uiを構築するためのコンポーネントライブラリ プロジェクト構造 認証システムのための基本的なファイル構造を設定しましょう src/ ├── components/ │ └── ui/ │ ├── field js │ └── toaster js ├── pages/ │ ├── signuppage js │ ├── loginpage js │ ├── resetpasswordpage js │ ├── profilepage js │ └── feedpage js ├── app js └── index js parse sdkの設定 では、アプリケーションでparseを初期化しましょう。次のファイルを作成します src/parseconfig js import parse from 'parse/dist/parse min js'; // initialize parse parse initialize("your app id", "your javascript key"); parse serverurl = "https //parseapi back4app com/"; export default parse; 「 your app id 」と「 your javascript key 」をあなたのback4appプロジェクトの資格情報に置き換えてください。これらはback4appダッシュボードのアプリ設定 > セキュリティとキーの下にあります。 次に、「 src/index js 」を更新して、parse設定をインポートします import react from 'react'; import reactdom from 'react dom/client'; import ' /index css'; import app from ' /app'; import ' /parseconfig'; const root = reactdom createroot(document getelementbyid('root')); root render( \<react strictmode> \<app /> \</react strictmode> ); ルートの設定 では、基本的なルーティング構造を「 src/app js 」に設定しましょう import react from 'react'; import { browserrouter as router, routes, route } from 'react router dom'; import {provider} from " /components/ui/provider"; // import pages import signuppage from ' /pages/signuppage'; import loginpage from ' /pages/loginpage'; import resetpasswordpage from ' /pages/resetpasswordpage'; import profilepage from ' /pages/profilepage'; import feedpage from ' /pages/feedpage'; function app() { return ( \<provider> \<router> \<routes> \<route path="/signup" element={\<signuppage />} /> \<route path="/login" element={\<loginpage />} /> \<route path="/reset password" element={\<resetpasswordpage />} /> \<route path="/profile" element={\<profilepage />} /> \<route path="/feed" element={\<feedpage />} /> \<route path="/" element={\<loginpage />} /> \</routes> \</router> \</provider> ); } export default app; uiコンポーネントの作成 認証ページを構築する前に、再利用可能なuiコンポーネントを作成しましょう。 まず、「 src/components/ui/toaster js 」を作成しましょう // a simple toast notification system export const toaster = { create ({ title, description, type }) => { alert(`${title} ${description}`); // in a real app, you would use chakra ui's toast system } }; 次に、作成します src/components/ui/field js import react from 'react'; import { formcontrol, formlabel, formerrormessage, formhelpertext } from '@chakra ui/react'; export const field = ({ label, children, errortext, helpertext, rest }) => { return ( \<formcontrol isinvalid={!!errortext} { rest}> {label && \<formlabel>{label}\</formlabel>} {children} {errortext ? ( \<formerrormessage>{errortext}\</formerrormessage> ) helpertext ? ( \<formhelpertext>{helpertext}\</formhelpertext> ) null} \</formcontrol> ); }; これで、認証システムを実装する準備が整いました! back4gramプロジェクト: 完全なコードを見つける こちら の ソーシャルネットワークサンプルプロジェクト をback4appで構築しました。 ステップ3 – ユーザー登録システムの作成 サインアップページの実装を始めましょう。このページでは、新しいユーザーがユーザー名、メールアドレス、パスワードを提供することでアカウントを作成できます。 「 src/pages/signuppage js 」という名前のファイルを作成します。 import react, { usestate } from 'react'; import { usenavigate, link as routerlink } from 'react router dom'; import { box, button, heading, input, vstack, link, text, flex } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function signuppage() { const \[username, setusername] = usestate(''); const \[email, setemail] = usestate(''); const \[password, setpassword] = usestate(''); const \[confirmpassword, setconfirmpassword] = usestate(''); const \[isloading, setisloading] = usestate(false); const \[showpassword, setshowpassword] = usestate(false); const \[errors, seterrors] = usestate({}); const navigate = usenavigate(); const validateform = () => { const newerrors = {}; if (!username trim()) { newerrors username = 'username is required'; } if (!email trim()) { newerrors email = 'email is required'; } else if (!/\s+@\s+\\ \s+/ test(email)) { newerrors email = 'email is invalid'; } if (!password) { newerrors password = 'password is required'; } else if (password length < 6) { newerrors password = 'password must be at least 6 characters'; } if (password !== confirmpassword) { newerrors confirmpassword = 'passwords do not match'; } seterrors(newerrors); return object keys(newerrors) length === 0; }; const handlesignup = async (e) => { e preventdefault(); if (!validateform()) { return; } setisloading(true); try { // create a new user using parse const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); toaster create({ title 'success', description 'account created successfully!', type 'success', }); navigate('/feed'); } catch (error) { console error('error signing up ', error); toaster create({ title 'error', description error message, type 'error', }); } finally { setisloading(false); } }; return ( \<box maxw="400px" mx="auto" p={4}> \<vstack spacing={6} align="stretch"> \<heading textalign="center">create an account\</heading> \<form onsubmit={handlesignup}> \<vstack spacing={4} align="stretch"> \<field isinvalid={!!errors username}> \<field label>username\</field label> \<input type="text" value={username} onchange={(e) => setusername(e target value)} /> {errors username && ( \<field errortext>{errors username}\</field errortext> )} \</field> \<field isinvalid={!!errors email}> \<field label>email\</field label> \<input type="email" value={email} onchange={(e) => setemail(e target value)} /> {errors email && ( \<field errortext>{errors email}\</field errortext> )} \</field> \<field isinvalid={!!errors password}> \<field label>password\</field label> \<flex position="relative"> \<input type={showpassword ? 'text' 'password'} value={password} onchange={(e) => setpassword(e target value)} /> \<button aria label={showpassword ? 'hide password' 'show password'} size="xs" position="absolute" right="0 25rem" top="50%" transform="translatey( 50%)" onclick={() => setshowpassword(!showpassword)} zindex={2} \> {showpassword ? 'hide' 'show'} \</button> \</flex> {errors password && ( \<field errortext>{errors password}\</field errortext> )} \</field> \<field isinvalid={!!errors confirmpassword}> \<field label>confirm password\</field label> \<input type={showpassword ? 'text' 'password'} value={confirmpassword} onchange={(e) => setconfirmpassword(e target value)} /> {errors confirmpassword && ( \<field errortext>{errors confirmpassword}\</field errortext> )} \</field> \<button type="submit" colorscheme="blue" isloading={isloading} mt={2} \> sign up \</button> \</vstack> \</form> \<text textalign="center"> already have an account?{' '} \<link as={routerlink} to="/login" color="blue 400"> log in \</link> \</text> \</vstack> \</box> ); } export default signuppage; このコードは、次の機能を持つサインアップフォームを作成します フォームバリデーション すべての必須フィールドが正しく入力されていることを確認します パスワードの表示切替 ユーザーが入力している内容を確認できるようにします エラーハンドリング バリデーションやサインアップの失敗に対して適切なエラーメッセージを表示します ローディング状態 サインアッププロセス中にローディングインジケーターを表示します back4appのユーザーサインアッププロセスの理解 このコードの重要な部分は、 handlesignup 関数で、back4appの parse user クラスを使用して新しいユーザーを作成します const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); サインアップ()を呼び出すと、back4appは 提供されたデータを検証します パスワードを安全にハッシュ化します データベースに新しいユーザーを作成します セッショントークンを作成して返します セッショントークンはparse sdkによって自動的に保存されます サインアップが成功すると、ユーザーは自動的にログインされるため、フィードページに直接リダイレクトできます。 back4gramアプリケーションでは、これは signuppage js で同様に実装されています。主な違いは、back4gramの実装がより高度なuiコンポーネントを使用し、追加のフィールドや検証ロジックを含む可能性があることです。 サインアップ機能が完了したので、次はログイン機能の実装に進みましょう。 back4gramプロジェクト 完全なコードを見つけるには、 こちら で、 ソーシャルネットワークのサンプルプロジェクト をback4appで構築しました。 ステップ4 – ユーザーログインの実装 では、ユーザーが資格情報で認証できるログインページを作成しましょう。 「 src/pages/loginpage js 」という名前のファイルを作成します。 import react, { usestate, useeffect } from 'react'; import { usenavigate, link as routerlink } from 'react router dom'; import { box, heading, input, button, text, vstack, link, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function loginpage() { const \[username, setusername] = usestate(''); const \[password, setpassword] = usestate(''); const \[isloading, setisloading] = usestate(false); const \[error, seterror] = usestate(''); const \[currentuser, setcurrentuser] = usestate(null); const navigate = usenavigate(); // check if a user is already logged in useeffect(() => { const checkcurrentuser = async () => { try { const user = await parse user current(); if (user) { setcurrentuser(user); navigate('/feed'); } } catch (error) { console error('error checking current user ', error); } }; checkcurrentuser(); }, \[navigate]); const handlelogin = async (e) => { e preventdefault(); if (!username || !password) { seterror('username and password are required'); return; } setisloading(true); try { // login with parse const loggedinuser = await parse user login(username, password); toaster create({ title 'login successful!', description `welcome back, ${loggedinuser getusername()}!`, type 'success', }); // redirect to feed after successful login navigate('/feed'); } catch (error) { toaster create({ title 'login failed', description error message, type 'error', }); seterror(error message); } finally { setisloading(false); } }; return ( \<box maxw="md" mx="auto" p={8} border="1px solid" bordercolor="gray 600" borderradius="md"> \<heading as="h1" size="xl" mb={6} textalign="center"> social network login \</heading> \<form onsubmit={handlelogin}> \<vstack spacing={4}> \<field label="username"> \<input type="text" value={username} onchange={(e) => setusername(e target value)} placeholder="your username" required /> \</field> \<field label="password" errortext={error} \> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="your password" required /> \</field> \<link as={routerlink} to="/reset password" alignself="flex end" fontsize="sm"> forgot password? \</link> \<button colorscheme="blue" width="full" type="submit" isloading={isloading} \> log in \</button> \</vstack> \</form> \<text textalign="center" mt={6}> don't have an account?{' '} \<link as={routerlink} to="/signup" color="blue 500"> sign up \</link> \</text> \</box> ); } export default loginpage; このログインページには以下の機能があります 自動リダイレクト ユーザーがすでにログインしている場合、フィードページに自動的にリダイレクトされます フォームバリデーション 提出前にユーザー名とパスワードが提供されていることを確認します エラーハンドリング ログイン試行が失敗した場合に適切なエラーメッセージを表示します ローディング状態 ログインプロセス中にローディングインジケーターを表示します パスワードリセットリンク パスワードリセットページへのリンクを提供します back4appのログインプロセスの理解 このコードの重要な部分は次のとおりです 既存のログインユーザーを確認するには parse user current() ユーザーをログインさせるには parse user login(username, password) ユーザーがback4appでログインするとき 資格情報はサーバーに送信されて検証されます 有効な場合、セッショントークンが生成されて返されます parse sdkはこのトークンを自動的に保存します ユーザーオブジェクトは現在のユーザーデータと共に返されます 保存されたセッショントークンは、その後のすべてのリクエストに対してparse sdkによって自動的に使用され、ユーザーはログインしたままになります。 back4gramアプリケーションでは、ログインシステムは loginpage js で同様に実装されていますが、より高度なuiコンポーネントやソーシャルログインオプションなどの追加機能がある可能性があります。 次に、パスワードリセット機能の実装に進みましょう。 back4gramプロジェクト: こちらで こちら 完全なコードを見つけてください ソーシャルネットワークサンプルプロジェクト をback4appで構築しました。 ステップ5 – パスワードリセット機能 次に、ユーザーがパスワードを忘れた場合にアカウントを回復できるパスワードリセットページを作成しましょう。 「 src/pages/resetpasswordpage js 」という名前のファイルを作成します。 import react, { usestate } from 'react'; import { link as routerlink } from 'react router dom'; import { box, heading, input, button, text, vstack, link, alert, alerticon, alerttitle, alertdescription, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function resetpasswordpage() { const \[email, setemail] = usestate(''); const \[isloading, setisloading] = usestate(false); const \[error, seterror] = usestate(''); const \[issuccess, setissuccess] = usestate(false); const handleresetpassword = async (e) => { e preventdefault(); if (!email) { seterror('email is required'); return; } // basic email validation const emailregex = /^\[^\s@]+@\[^\s@]+\\ \[^\s@]+$/; if (!emailregex test(email)) { seterror('invalid email format'); return; } setisloading(true); seterror(''); try { // request password reset await parse user requestpasswordreset(email); setissuccess(true); toaster create({ title 'email sent', description 'check your inbox for password reset instructions ', type 'success', }); } catch (error) { toaster create({ title 'reset request failed', description error message, type 'error', }); seterror(error message); } finally { setisloading(false); } }; return ( \<box maxw="md" mx="auto" p={8} border="1px solid" bordercolor="gray 600" borderradius="md"> \<heading as="h1" size="xl" mb={6} textalign="center"> reset password \</heading> {issuccess ? ( \<alert status="success" borderradius="md"> \<alerticon /> \<box> \<alerttitle>email sent successfully!\</alerttitle> \<alertdescription> check your inbox for password reset instructions \</alertdescription> \</box> \</alert> ) ( \<form onsubmit={handleresetpassword}> \<vstack spacing={4}> \<text> enter your email and we'll send you instructions to reset your password \</text> \<field label="email" errortext={error} \> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="your email address" required /> \</field> \<button colorscheme="blue" width="full" type="submit" isloading={isloading} \> send instructions \</button> \<link as={routerlink} to="/login" color="blue 500"> back to login \</link> \</vstack> \</form> )} \</box> ); } export default resetpasswordpage; このパスワードリセットページには メール検証 有効なメール形式が提供されていることを確認します 成功状態 リセットメールが送信された後に成功メッセージを表示します エラーハンドリング リセットリクエストが失敗した場合に適切なエラーメッセージを表示します 読み込み状態 リセットリクエストプロセス中に読み込みインジケーターを表示します back4appのパスワードリセットプロセスの理解 このコードの重要な部分は、back4appの parse user requestpasswordreset(email) メソッドを使用して、ユーザーにパスワードリセットメールを送信することです。 ユーザーがback4appでパスワードリセットをリクエストすると back4appは、メールがデータベースに存在することを確認します メールが見つかった場合、リセットメールがユーザーに送信されます メールには、安全なトークンを含むリンクが含まれています ユーザーがリンクをクリックすると、パスワードリセットページにリダイレクトされます 新しいパスワードを設定した後、彼らは新しい資格情報でログインできます back4gramアプリケーションでは、パスワードリセット機能が同様に実装されています。 resetpasswordpage js を使用し、同じback4app apiメソッドを使用していますが、より高度なuiコンポーネントや追加機能がある可能性があります。 コア認証機能を実装したので、セッション管理に焦点を当てましょう。 back4gramプロジェクト: 完全なコードを見つけるには こちら の ソーシャルネットワークサンプルプロジェクト をback4appで構築しました。 ステップ6 – セッション管理と永続性 認証システムの重要な側面の1つは、適切なセッション管理です。これにより、ユーザーはアプリケーションをナビゲートしている間にログインしたままであり、セッションが安全であることが保証されます。 セッションチェックと管理を示すために、フィードページの簡略版を作成しましょう。 「 src/pages/feedpage js 」という名前のファイルを作成します。 import react, { usestate, useeffect } from 'react'; import { usenavigate } from 'react router dom'; import { box, heading, button, text, vstack, hstack, spinner, center, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; function feedpage() { const \[isloading, setisloading] = usestate(true); const \[currentuser, setcurrentuser] = usestate(null); const navigate = usenavigate(); // check if user is authenticated useeffect(() => { const checkauth = async () => { try { console log('checking authentication '); const user = await parse user current(); if (!user) { console log('no user found, redirecting to login'); navigate('/login'); return; } console log('user authenticated ', user id, user get('username')); setcurrentuser(user); setisloading(false); } catch (error) { console error('error checking authentication ', error); navigate('/login'); } }; checkauth(); }, \[navigate]); // function to handle logout const handlelogout = async () => { try { await parse user logout(); navigate('/login'); } catch (error) { console error('error logging out ', error); toaster create({ title 'error', description 'failed to log out please try again ', type 'error', }); } }; if (isloading) { return ( \<center h="100vh"> \<spinner size="xl" /> \</center> ); } return ( \<box maxw="800px" mx="auto" p={8}> \<hstack justify="space between" mb={8}> \<heading>social network feed\</heading> \<hstack> \<text>welcome, {currentuser get('username')}\</text> \<button onclick={handlelogout} colorscheme="red" variant="outline"> log out \</button> \</hstack> \</hstack> \<vstack align="stretch" spacing={4}> \<box p={4} borderwidth={1} borderradius="md"> \<text>this is your feed when authenticated with back4app, you'll see content here \</text> \<text mt={2}>your user id {currentuser id}\</text> \<text>your email {currentuser get('email')}\</text> \</box> \</vstack> \</box> ); } export default feedpage; このフィードページは次のことを実装しています 認証チェック コンテンツを表示する前にユーザーがログインしていることを確認します 自動リダイレクト ユーザーセッションが見つからない場合、ログインページにリダイレクトします ログアウト機能 ユーザーがログアウトし、セッションをクリアできるようにします ユーザー情報表示 現在ログインしているユーザーに関する情報を表示します back4appのセッション管理の理解 back4appはセッションをいくつかの方法で処理します 自動セッションストレージ parse sdkはログイン後にセッショントークンを自動的に保存します 現在のユーザーアクセス 現在のユーザーには parse user current() セッションの有効期限 セッションは通常、設定された期間(back4appで設定可能)後に期限切れになります ログアウト セッションを終了するには parse user logout() back4gramのような本番アプリケーションでは、セッション管理はしばしばより複雑です。 messagespage js ファイルの中で、コンポーネントの最初に認証がどのようにチェックされるかを見ることができます useeffect(() => { const checkauth = async () => { try { console log('checking authentication '); const user = await parse user current(); if (!user) { console log('no user found, redirecting to login'); navigate('/login'); return; } console log('user authenticated ', user id, user get('username')); setcurrentuser(user); fetchconversations(user); } catch (error) { console error('error checking authentication ', error); navigate('/login'); } }; checkauth(); // clean up subscriptions when component unmounts // }, \[navigate]); コンポーネントレベルでの認証確認のこのパターンは、back4appを使用するreactアプリケーションで一般的です。 セッションセキュリティの考慮事項 back4appでセッション管理を実装する際は、これらのセキュリティ対策を考慮してください 自動セッション無効化 一定期間の非活動後にセッションを無効にするようback4appを設定します 安全なストレージ セッショントークンが安全に保存されることを確認します(parse sdkがこれを自動的に処理します) httpsのみ セッショントークンの傍受を防ぐために常にhttpsを使用します 敏感な操作でのログアウト パスワード変更などの敏感な操作には再認証を要求します 認証システムを完成させるために、プロファイル管理の実装方法を見ていきましょう。 back4gramプロジェクト 完全なコードを見つけるには こちら で、 ソーシャルネットワークのサンプルプロジェクト をback4appで構築しました。 ステップ7 – ユーザープロファイル管理の追加 私たちの認証システムの最終的な部分はユーザープロファイル管理です。これにより、ユーザーは自分のプロファイル情報を表示および更新できます。 「 src/pages/profilepage js 」という名前のファイルを作成します。 import react, { usestate, useeffect } from 'react'; import { usenavigate } from 'react router dom'; import { box, button, heading, text, vstack, hstack, input, textarea, avatar, formcontrol, formlabel, spinner, center, } from '@chakra ui/react'; import parse from 'parse/dist/parse min js'; import { toaster } from ' /components/ui/toaster'; import { field } from ' /components/ui/field'; function profilepage() { const \[user, setuser] = usestate(null); const \[username, setusername] = usestate(''); const \[email, setemail] = usestate(''); const \[bio, setbio] = usestate(''); const \[isloading, setisloading] = usestate(true); const \[isupdating, setisupdating] = usestate(false); const \[selectedfile, setselectedfile] = usestate(null); const \[avatarurl, setavatarurl] = usestate(null); const navigate = usenavigate(); // fetch user data useeffect(() => { const fetchuserdata = async () => { try { const currentuser = await parse user current(); if (!currentuser) { navigate('/login'); return; } setuser(currentuser); setusername(currentuser get('username') || ''); setemail(currentuser get('email') || ''); setbio(currentuser get('bio') || ''); // get avatar if available const avatar = currentuser get('avatar'); if (avatar) { setavatarurl(avatar url()); } setisloading(false); } catch (error) { console error('error fetching user data ', error); toaster create({ title 'error', description 'failed to load profile data', type 'error', }); navigate('/login'); } }; fetchuserdata(); }, \[navigate]); // handle profile update const handleupdateprofile = async (e) => { e preventdefault(); setisupdating(true); try { if (!user) return; user set('username', username); user set('email', email); user set('bio', bio); // handle avatar upload if a file is selected if (selectedfile) { const parsefile = new parse file(selectedfile name, selectedfile); await parsefile save(); user set('avatar', parsefile); setavatarurl(parsefile url()); } await user save(); toaster create({ title 'success', description 'profile updated successfully', type 'success', }); } catch (error) { console error('error updating profile ', error); toaster create({ title 'error', description error message, type 'error', }); } finally { setisupdating(false); } }; // handle avatar selection const handlefilechange = (e) => { if (e target files && e target files\[0]) { setselectedfile(e target files\[0]); // create a preview url const previewurl = url createobjecturl(e target files\[0]); setavatarurl(previewurl); } }; // handle logout const handlelogout = async () => { try { await parse user logout(); navigate('/login'); } catch (error) { console error('error logging out ', error); } }; if (isloading) { return ( \<center h="100vh"> \<spinner size="xl" /> \</center> ); } return ( \<box maxw="800px" mx="auto" p={8}> \<hstack justify="space between" mb={8}> \<heading>your profile\</heading> \<button onclick={handlelogout} colorscheme="red" variant="outline"> log out \</button> \</hstack> \<box p={8} borderwidth={1} borderradius="md"> \<form onsubmit={handleupdateprofile}> \<vstack spacing={6} align="start"> \<hstack spacing={8} w="full" align="start"> \<vstack align="center" minw="150px"> \<avatar size="2xl" src={avatarurl} name={username} mb={4} /> \<formcontrol> \<formlabel htmlfor="avatar upload" cursor="pointer" textalign="center"> \<button as="span" size="sm"> change avatar \</button> \<input id="avatar upload" type="file" accept="image/ " onchange={handlefilechange} display="none" /> \</formlabel> \</formcontrol> \</vstack> \<vstack spacing={4} flex="1"> \<field label="username" w="full"> \<input value={username} onchange={(e) => setusername(e target value)} /> \</field> \<field label="email" w="full"> \<input type="email" value={email} onchange={(e) => setemail(e target value)} /> \</field> \<field label="bio" w="full"> \<textarea value={bio} onchange={(e) => setbio(e target value)} placeholder="tell us about yourself" rows={4} /> \</field> \</vstack> \</hstack> \<button type="submit" colorscheme="blue" isloading={isupdating} alignself="flex end" \> save changes \</button> \</vstack> \</form> \</box> \</box> ); } export default profilepage; this profile page provides users with the ability to 1\ view profile information see their username, email, and bio 2\ update profile details change their username, email, and bio 3\ upload a profile picture select and upload a profile image 4\ log out end their session and return to the login page \### understanding back4app's user data management let's examine the key aspects of how back4app handles user data management \#### file uploads with parse file one powerful feature of back4app is the ability to easily handle file uploads using `parse file` ```javascript if (selectedfile) { const parsefile = new parse file(selectedfile name, selectedfile); await parsefile save(); user set('avatar', parsefile); setavatarurl(parsefile url()); } 新しい parse file を作成すると、back4app ファイル(画像、文書など)を取得します 安全なストレージにアップロードします ユーザーオブジェクトと一緒に保存できる参照を返します ファイルをurl経由でアクセス可能にします カスタムユーザーフィールドの追加 back4appの parse user クラスは、デフォルトのフィールドを超えてカスタムフィールドで拡張できます。私たちの例では、次のように追加しました bio ユーザーの説明用のテキストフィールド avatar プロフィール写真用のファイルフィールド アプリケーションのユーザープロフィールに必要なカスタムフィールドを追加できます user set('bio', bio); back4gramアプリケーションでは、 profilepage js が似た機能を実装していますが、より多くの機能と複雑なuiを備えています。フォロワー数、投稿統計、より堅牢な画像処理などの追加フィールドが含まれています。 back4gramプロジェクト: を見つける こちら 完全なコードを ソーシャルネットワークサンプルプロジェクト を使用して構築したback4app ステップ8 – 認証システムのテストとセキュリティ 認証システムを構築したので、適切にテストし、セキュリティを確保する方法について話しましょう。 認証フローのテスト 認証システムをテストする際は、これらのフローをそれぞれ確認する必要があります: ユーザー登録 ユーザーが有効な資格情報でアカウントを作成できることをテストする 入力検証 無効な入力に対して適切なエラーが表示されることを確認する ログインプロセス ユーザーが正しい資格情報でログインできることを確認する ログイン失敗 不正な資格情報に対して適切なエラーが表示されることを確認する パスワードリセット パスワードリセットフローがエンドツーエンドで機能することを確認する セッションの持続性 ユーザーがページ訪問間でログインしたままであることを確認する ログアウトプロセス ユーザーが適切にログアウトでき、セッションが終了することを確認する 避けるべき一般的なセキュリティ脆弱性 認証システムを構築する際は、これらの一般的なセキュリティ問題に注意してください パスワードの保存 パスワードをプレーンテキストで保存しないでください。back4appが自動的にこれを処理します。 ブルートフォース攻撃 ログイン試行のレート制限を実装してください。back4appはこの機能を提供します。 クロスサイトスクリプティング (xss) スクリプトインジェクションを防ぐためにユーザー入力をサニタイズしてください。 クロスサイトリクエストフォージェリ (csrf) リクエストの真正性を確認するために適切なトークンを使用してください。 不適切な直接オブジェクト参照 urlに機密idや参照を公開しないでください。 back4appのセキュリティベストプラクティス back4appは、活用すべきいくつかのセキュリティ機能を提供しています 1\ クラスレベルの権限 (clp) back4appのダッシュボードでは、クラスレベルの権限を設定して、誰がオブジェクトを読み書き削除できるかを制御できます back4appのダッシュボードに移動します データベース → ブラウザに移動します ユーザークラスの「セキュリティ」ボタンをクリックします 権限を適切に設定します \[image back4appのクラスレベルの権限画面にユーザークラスのセキュリティ設定が表示されています] ユーザークラスの一般的な設定には、次のものが含まれます 特定のフィールド(ユーザー名、アバター)に対する公開読み取りアクセスのみ 公開の書き込みまたは削除アクセスはありません 認証されたユーザーのみが自分のレコードを更新できます 2\ アクセス制御リスト(acl) 個々のオブジェクトについては、aclを使用してアクセスを制御できます // set an acl that only allows the current user to read and write this object const useracl = new parse acl(parse user current()); userobject setacl(useracl); await userobject save(); これにより、オブジェクトを作成したユーザーのみがアクセスまたは変更できることが保証されます。 3\ マスターキーの使用 back4appは、セキュリティチェックをバイパスするマスターキーを提供します。クライアント側のコードでこれを公開しないでください // never do this in client side code parse cloud usemasterkey(); // this should only be used in cloud code 代わりに、特権が必要な操作にはcloud functionsを使用してください。 4\ メール認証 ユーザーが有効なメールアドレスを提供することを確認するために、back4appの設定でメール認証を有効にしてください。 back4appのダッシュボードに移動します アプリ設定 → メール設定に移動します メールアダプターを設定します メール認証を有効にします \[画像 back4appメール設定の構成画面] 5\ 二要素認証 追加のセキュリティのために、back4app cloud functionsを使用して二要素認証を実装できます。これにより、ユーザーはログイン時に2番目の確認手段(通常は電話またはメールに送信されたコード)を提供する必要があります。 レート制限の実装 ブルートフォース攻撃から保護するために、cloud functionsを使用してレート制限を実装できます。 // cloud function to handle login with rate limiting parse cloud define("securelogin", async (request) => { const { username, password } = request params; // check for too many failed attempts const query = new parse query("loginattempt"); query equalto("username", username); query greaterthan("createdat", new date(date now() 15 60 1000)); // last 15 minutes const attempts = await query count(); if (attempts >= 5) { throw new error("too many login attempts please try again later "); } try { // attempt to log in const user = await parse user login(username, password); return { success true, user user tojson() }; } catch (error) { // record failed attempt const loginattempt = parse object extend("loginattempt"); const attempt = new loginattempt(); attempt set("username", username); await attempt save(null, { usemasterkey true }); throw error; } }); 結論 このチュートリアルでは、back4appを使用してソーシャルネットワークアプリケーションの包括的な認証システムを構築しました。ユーザー登録、ログイン、パスワードリセット、プロフィール管理機能を実装し、すべてback4appの組み込みユーザー管理機能によって支えられています。 学んだことを振り返りましょう back4appのユーザー管理システム back4appのparse serverがどのように組み込みのユーザー認証を提供するかを学びました。 parse user クラスを使用します。 ユーザー登録 新しいユーザーアカウントをback4appのデータベースに作成するサインアップフォームを実装しました。 ユーザーログイン ユーザーを認証し、セッションを管理するログインシステムを作成しました。 パスワードリセット 回復メールを送信する安全なパスワードリセット機能を追加しました。 セッション管理 ユーザーセッションを維持し、ルートを保護する方法を学びました。 プロフィール管理 ユーザーが情報を更新し、プロフィール写真をアップロードできるプロフィールページを構築しました。 セキュリティのベストプラクティス back4appのセキュリティ機能を使用して認証システムを保護する方法を探求しました。 back4appを使用することで、複雑なバックエンドインフラを構築するのではなく、優れたユーザーエクスペリエンスの創造に集中できました。back4appを支えるparse serverは、必要なすべての認証apiを提供し、ユーザーデータの安全性を確保しています。 あなたが構築した認証システムは、ソーシャルネットワークアプリケーションの基盤を形成します。これが整ったことで、back4appをバックエンドサービスとして使用しながら、投稿、コメント、いいね、ダイレクトメッセージなどの機能を追加してアプリケーションを拡張できます。 次のステップ ソーシャルログイン統合 back4appのoauth機能を使用して、google、facebook、または他のプロバイダーでのログインを追加します。 強化されたセキュリティ 追加のセキュリティのために二要素認証を実装します。 ユーザーロール 異なるタイプのユーザーのために役割ベースのアクセス制御を設定します。 リアルタイム機能 back4appのライブクエリを使用して、リアルタイムメッセージングと通知を追加します。 back4gramソーシャルネットワークアプリケーションの完全なコードは、 githubリポジトリ https //github com/templates back4app/back4gram をチェックできます。 back4appの強力なバックエンドサービスとparse serverの統合により、安全でスケーラブルなソーシャルネットワークアプリケーションを構築するための優れた選択肢となります。組み込みのユーザー管理機能を活用することで、最小限の労力で堅牢な認証システムを作成でき、アプリケーションを際立たせるユニークな機能の作成に集中できます。