0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

タスク管理ツールをReact + ASP.Coreで作る019JWTトークン機能追加

Last updated at Posted at 2022-11-09

前回の続きです

概要

016~018の記事で、認証機能の追加、ログイン用ユーザーの追加、ログイン画面、JWTトークンの生成・クライアントでの取得機能を作りました。
認証情報をやり取りする土台が出来たので、いよいよ認証されているユーザーにのみ特定の操作を許す。という仕様を盛り込むことが可能になります。
それでは構築していきましょう。

ガイド

全体Index:タスク管理ツールをReact + ASP.Coreで作る - Index

認証機能追加の一連の流れ

構築

認証情報をクライアントサイドに保管する機能の追加

まず、認証された際のトークンをクライアントに保管し、認証後にクライアントに問い合わせるときは認証情報付きで問い合わせるように仕様を変更します。

次に、認証情報をAPIに乗せて、認証するようにします。

まず、認証時にjwtトークンを記録(「tasket_jwt_token」という名称でブラウザに保存)します

Login.tsx
    const submit = async (e: SyntheticEvent) => {
        e.preventDefault();
        const response = await fetch('https://localhost:5001/account/login',
        {
            method : 'POST',
            headers:{'Content-Type' : 'application/json'},
            credentials: 'include',
            body: JSON.stringify({
                email,
                password
            })
        });
        const content = await response.json();
        const status = await response.status

        setResultcode(status);
        setResultTitle(content.title);
        if(status==200){
            setName(content.username);
            setToken(content.token);

+            window.localStorage.setItem('tasket_jwt_token', content.token);

        }

    }
参考:TaskList.tsx全体(開くと表示)
Login.tsx
import React, { SyntheticEvent, useState } from 'react';

const Login = (
    ) => 
{
    
    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [resultcode, setResultcode] = useState(0);
    const [resultTitle, setResultTitle] = useState('');
    const [token, setToken] = useState('');



    const submit = async (e: SyntheticEvent) => {
        e.preventDefault();
        const response = await fetch('https://localhost:5001/account/login',
        {
            method : 'POST',
            headers:{'Content-Type' : 'application/json'},
            body: JSON.stringify({
                email,
                password
            })
        });
        const content = await response.json();
        const status = await response.status

        setResultcode(status);
        setResultTitle(content.title);
        if(status==200){
            setName(content.username);
            setToken(content.token);
            
            window.localStorage.setItem('tasket_jwt_token', content.token);

        }

    }

    
    return (
        <>
        <form onSubmit={submit}>
            <h2>Sign in</h2>

            <ul>

                <li>
                    <label>email</label>
                    <input type="email" placeholder="name@example.com" required 
                        onChange = {e => setEmail(e.target.value)}            
                    />
                </li>

                <li>                    
                    <label>password</label>
                    <input type="password" placeholder="Password" required 
                        onChange = {e => setPassword(e.target.value)}            
                    />
                </li>
            </ul>

            <button type="submit">Sign in</button>

        </form>
        
        <h2>Response</h2>

        <ul>
            <li>
                {resultcode!=0 && <>{resultcode==200 ? <>Login Success</> : <>Login Fail</>}</>}
            </li>

            <li>
                {resultcode==200 && <>Name:{name}</>}
            </li>

            <li>
                {resultcode!=0 && <>Code:{resultcode}</>}
            </li>

            <li>
                {resultcode!=0 && <>msg:{resultTitle}</>}
            </li>

            <li>
                {resultcode!=0 && <p>token : {token}</p>}
            </li>
        </ul>
        </>
    );

}

export default Login;

API問い合わせ時に認証トークンを含めるように仕様変更

トークン取得後はブラウザに保管したトークンをAPIでの問い合わせ時には含めるように仕様を変更します。
具体的には、api.tsのリクエスト時にトークンが存在するかどうかを確認し、存在する場合は問い合わせ時に含めるためのコードを追加します

api.ts

import axios, { AxiosResponse } from "axios";
import { Task } from "../models/Task";

axios.defaults.baseURL = "https://localhost:5001"; 


+ axios.interceptors.request.use(config => {
+     const token = window.localStorage.getItem('tasket_jwt_token');
+     if(token) config.headers!.Authorization = `Bearer ${token}`
+     return config;
+ })

const Tasks = {
    index: () => axios.get<Task[]>(`/task`).then((response: AxiosResponse<Task[]>)=>response.data),
    details: (id:string) => axios.get<Task>(`/task/${id}`).then((response: AxiosResponse<Task>)=>response.data),
    create: (task:Task) => axios.post<Task>(`/task/create`, task).then((response: AxiosResponse<Task>)=>response.data),
    update: (task:Task) => axios.post<Task>(`/task/update`, task).then((response: AxiosResponse<Task>)=>response.data),
    delete:(id:string) => axios.post<void>(`/task/delete/${id}`),
}


const api = {
    Tasks,
}

export default api;

サーバーサイドに認証制御を追加

これまでの改修でサーバーサイドでは認証されたユーザーからのアクセスかどうかを把握する機能は作られていますが、認証によって動作の分岐などは起こっていない(あらゆる操作を許している)ので、今回コントローラーの一部の動作に制限を入れてみます。

具体的には、タスクごとの詳細情報を取得する関数を認証時のみ動作する様に変更します。

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;


        {
            return await _context.t_tasks.ToListAsync();
        }
+        [Authorize]
        [HttpGet("{id}")]
        public async Task<ActionResult<t_task>> Details(Guid id)
        {

この状態でサーバーサイド・クライアントサイドともに再起動を行うと、以下の様になります

動作させてみる

今回は以上です。続きは次回です

TAG:V000-16-00

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?