Authの適用


🧐 概要


Webサービスにはログインが必要な機能があります.
したがって、ログインしていない非ユーザーに対しては、アクセスをブロックしてください.
予期せぬ事態を防ぐ.
データベースに変な値が...
この文書では、Reactのhoc(高次成分)とノードのセッションを使用します.
Authの適用方法をまとめます.

📋 セッションの作成-ノード


セッションは、サーバ側が管理するCookieにたとえることができます.
クライアントにセッションIDを提供し、ブラウザが終了する前にセッションを保持します.
セッションとCookieのパージは他の文書で行われ、ノードでセッションの作成が続行されます.
npm install express-session       // 세션 관리용 미들웨어
npm install express-mysql-session // MySQL에 세션 저장
npm install session-file-store    // 파일에 세션 저장
npm install fortune-session       // MongoDB, Redis, Postgres, NeDB
npm install connect-mongo         // MongoDB
セッションはサーバメモリに格納されます.これは、サーバがシャットダウンすると初期化されるため、通常はデータベースに関連付けられて、このような状況を防止します.
npm install express-session  
デフォルトでは、セッションを処理するには、上記のモジュールをインストールする必要があります.
そして、開発者のDBによってインストールするモジュールが異なります.
現在連動されているMySQLをもとに述べます.
const session = require('express-session');
	// 세션 미들웨어 선언
const MySQLStore = require('express-mysql-session')(session);
	// 세션값 저장소 선언 ( MySQL )

app.use(session({
    secret              : configF.secret, 
    resave              : false,
    saveUninitialized   : false,
    secure              : true,
    HttpOnly            : true,
    store               : new MySQLStore({
        host    : configL.host,
        port    : 3306,
        user    : configL.user,
        password: configL.password,
        database: configL.database
    })
}));
使用方法は次のとおりです.
各値は、プロファイルから個別に抽出されます.
以下はオプションの説明です.
  • secret:クッキーの改ざんを阻止する暗号化値.暗号化セッション
  • resave:セッションをリクエストごとに再保存します.
  • saveUnified:初期化されていないセッションを保存します.
  • secure:http環境でのみ通信セッション
  • HttpOnly:クライアントがCookieを表示できるかどうかを指定します.
  • store:セッションを格納するリポジトリを指定する
  • 他にも選択肢がたくさんあります.次のリンクで見つけることができます.
    つまり、セッションを作成するときは、必要に応じてセッション変数を設定して管理できます.
    crypto.pbkdf2(userpw,results[0].salt,108326,64,'sha512',(err,key)=>{
              const realPW = key.toString('base64');
              if (realPW==results[0].pw){
                  req.session.displayName=userid;
                  console.log('Auth complete');
                           
    ルータの一部にログインします.
    クライアントが入力した値は暗号化され、データベースに格納されている値と一致します.
    ユーザIDをセッションのpaylayname変数に格納します.
    このようにセッション変数を指定できます.
    req.session.[変数名]=値
    セッション変数をグローバル変数として使用できます.
    最後に、セッションを削除します.
    req.session.destroy(); // 로그아웃 라우터에 선언합니다.

    📋 フロントエンドへ転送

    app.get('/api/getSession',(req,res)=>{
        if (typeof req.session.displayName!=='undefined'){
            res.send({isAuth:true,ID:req.session.displayName});
        }else{
            res.send({isAuth:false});
        }
    セッション変数が宣言されていないタイプは定義されていません.
    したがって、タイプ値に基づいて分岐し、isauth値とID値を渡す.

    📋 ログインの検証-リカバリ


    最初に試したのは、入力したisAuth値に基づいてレンダリングする要素を変更することです.
    const [Session,setSession] = useState("")
    
    useEffect(()=>{
            axios.get('/api/getSession')
            .then(response=>{
                setSession(response.data);
            })
        },[])
        
    const sessionValue = (Session) =>{
        if (Session.length>0){
            return true;
        }else{
            return false;
        }
    }
    
    return (
     {sessionValue(Session) ?
     	<div>
        	로그인된 유저입니다.
    	</div>
        :
    	<Redirect to='forbidden'/>
     
    )
    上記の方法で検証できますが.
    インポートセッションには小さな遅延があります.
    したがって、セッションがfalseの場合、ページは一時的にレンダリングされ、再びtrueの場合、ページはレンダリングされます.
    もちろん、直接転送することなく、空のdivラベルで包むことができます.
    これは完全な方法ではありません.不要なセッションを取得するためにコードを書く必要があります.
    そこで高次素子,HOC方式を採用した.

    📋 HOC - React


    構成部品を作成するときに、一般的な繰り返し機能があります.
    Webソケット、Navbar...待ってるはずだ
    これらの機能を最上位コンポーネントとして、必要なコンポーネントとして配布するだけです.
    この文書では、ログイン検証に関連するhocを作成します.

    📎 HOC Action / Reducer

    export function auth(){
        const request=axios.get('/api/getSession')
        .then(response=>response.data);
    
        return {
            type:AUTH_USER,
            payload: request
        }
    // user_action.js
    まずauth actionを宣言します.
    axios.あらかじめサーバ上で作成した/api/getSessionにgetアクセスして値を取得するアクションを作成します.
    case AUTH_USER:
                return {...state, authData: action.payload}
                break;
                
    // user_reducer.js
    同様に、減速機を作成します.
    複数の動作があるため、switch文で記述されています.

    📎 HOC function

    export default function (SpecificComponent, option, adminRoute = null){
        function AuthenticationCheck(props){
          const dispatch = useDispatch();
          useEffect(()=>{
            dispatch(auth())
            .then(response=>{
                if (response.payload.isAuth){
                    if (option==false){
                        props.history.push('/authError');
                    }
                }else{
                    if (option==true && SpecificComponent.name!=='Logout'){
                        props.history.push('/authError');
                    }
                }
            })
        },[])
    
        return <SpecificComponent idx={props.match.params.idx} filter={props.match.params.filter} text={props.match.params.text} name={props.match.params.name}/>
        }
      return AuthenticationCheck
    }
    
    // auth.js
    まずはParameterをご紹介します.
  • 特定ユニット:適合部品
  • option:接続できるかどうかはログインするかどうかによる
    2-1. true:ログインユーザーのみが接続可能
    2-2. false:ログインしていないユーザーのみ接続できます
    2-3. null:誰でも接続可能
  • 管理者接続の有無
  • dispatch(auth())
    .then(response=>{
          if (response.payload.isAuth){
              if (option==false){
                  props.history.push('/authError');
              }
          }else{
              if (option==true && SpecificComponent.name!=='Logout'){
                  props.history.push('/authError');
              }
           }
    authアクションのisauth値でログインしていることを確認します.
    また、option値を使用してアクセス可能かどうかを決定することもできます.
    3番目のパラメータAdminRoute値を使用すると、管理者ページなどのアクセス性を制御できます.
    私は彼を別の共通の禁止ページに移動させた.
    로그아웃의 경우 landingPage로 Redirect 시키도록 되어있는데, 
    Redirect 직전에 isAuth값이 false가 되어 authError가 발생합니다.
    임시조치로 logout의 경우 authError가 발생하지 않도록 막아두었습니다.
    아예 logout 라우터의 옵션을 null로 두어도 되지만
    req.session.destroy()의 의미없는 호출은 비효율적이라고 판단했습니다.

    📋 App.js

    <Route exact path="/" component={Auth(LandingPage)}/>
    <Route path="/authError" component={Forbidden}/>
    <Route path="/login" component={Auth(LoginPage,false)}/>
    <Route path="/register" component={Auth(RegisterPage,false)}/>
    <Route path="/logout" component={Auth(Logout,true)}/>
    <Route path="/board/list/:idx" component={Auth(Board)}/>
    
    // App.js
    「Route」セクションでは、上の図に示すように、Authを使用して構成部品を囲むことができます.
    ここで注意すべきはmatch paramsに渡される値の処理である.
    <Route path="/board/list/:idx" component={Auth(Board)}/>
    例えば、idx paramsはBoardではなくAuth素子に伝達される.
    return <SpecificComponent idx={props.match.params.idx} filter={props.match.params.filter} text={props.match.params.text} name={props.match.params.name}/>
    したがって、上記の図に示すようにpropsとして素子に渡さなければならない.
    盲目的にアイテムを増やすのを防ぐために
    場合によってはAuthを迂回しないことを考えた.