ã€Pyhon/Django】ログイン機能カスタマイズ

最近ã¯ã‚‚ã£ã±ã‚‰Djangoã§ã®ã‚µã‚¤ãƒˆæ§‹ç¯‰ã®æ„Ÿè§¦ã‚’探りãªãŒã‚‰é–‹ç™ºã—ã¦ã„ã¾ã™ï¼ˆèª¿ã¹ã‚‹æ™‚é–“ã®æ–¹ãŒåœ§å€’çš„ã«å¤šã„ã§ã™ãŒï¼‰
当ブログã§ã‚‚Djangoã§ã®æ©Ÿèƒ½è¿½åŠ ã‚„ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºã«ã¤ã„ã¦æŠ•ç¨¿ã—ã¦ãŠã‚Šã¾ã™ã€‚
ãã®ä¸­ã§ã€å…ˆæ—¥ã®è¨˜äº‹ã€Pyhon/Django】カスタムユーザã¨ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒ­ã‚°ã‚¤ãƒ³ï¼‘ã«ã¤ã„ã¦
開発ã—ã¦ã„ã上ã§ä¿®æ­£ãŒå¿…è¦ãªéƒ¨åˆ†ã‚りã¾ã—ãŸã®ã§ã€ã“ã¡ã‚‰ã«è¨˜è¼‰ã—ã¦ã„ãã¾ã™ã€‚

 

修正ãŒå¿…è¦ãªéƒ¨åˆ†

ログイン機能ã®ä¸­ã§ãƒ­ã‚°ã‚¤ãƒ³å¾Œã®ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆã‚’指定ã—ã¦ã„ã‚‹ã®ã§ã™ãŒ
パスを固定値ã«ã—ã¦ã„ã‚‹ãŸã‚ã«ãƒ­ã‚°ã‚¤ãƒ³ãŒå¿…è¦ãªé ˜åŸŸã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãŸéš›ã«
『ログイン画é¢â‡’å…ƒã®ãƒšãƒ¼ã‚¸ã«æˆ»ã‚‹ã€ã¨ã„ã†åˆ¶å¾¡ãŒã§ãã¾ã›ã‚“。

ã‹ã£ã“悪ã„ã®ã§ä¿®æ­£ã—ã¾ã™ã€‚

å‰å›žã®ã‚³ãƒ¼ãƒ‰ãŠã•らã„

対象ã¨ãªã‚‹ã®ã¯views.py部分ã«ãªã‚Šã¾ã™ã€‚
ログイン処ç†ã®è©²å½“部分ã®ã¿æŠœç²‹ã—ã¦ã„ã¾ã™ã€‚
class LoginView(View):
    def post(self, request, *args, **kwargs):
        template_name = 'login.html'
        success = 'home'
        form = LoginForm(data=request.POST)
        if form.is_valid():
            # フォームã‹ã‚‰'email'を読ã¿å–ã‚‹
            email = form.cleaned_data.get('email')
            # フォームã‹ã‚‰'password'を読ã¿å–ã‚‹
            password = form.cleaned_data.get('password')
            auth_object = EmailAuthBackend()
            user = auth_object.authenticate(email=email, password=password)
            if user is not None:
                #èªè¨¼å‡¦ç†
                login(request, user, backend='user.auth.EmailAuthBackend')
                return redirect(success)
            else:
                return render(request, template_name, {'context': 'ログインã«å¤±æ•—ã—ã¾ã—ãŸ'})

    def get(self, request, *args, **kwargs):
        template_name = 'login.html'
        form = LoginForm(request.POST)
        return render(request, template_name, {'context': 'get'})
æˆåŠŸã—ãŸå ´åˆã«successã§æŒ‡å®šã—ãŸ"home"ã«å¿…ãšãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã—ã¦ã„ã‚‹ãŸã‚ 元々アクセスã—よã†ã¨ã—ã¦ã„ãŸURLã®æƒ…å ±ãŒãªããªã£ã¦ã—ã¾ã£ã¦ã„ã¾ã™ã€‚

修正後ã®ã‚½ãƒ¼ã‚¹

views.pyã¨login.htmlã®ï¼’ã¤ã®ãƒ•ァイルを修正ã—ã¾ã™ã€‚
ã¾ã™ã¯views.py
class LoginView(View):
    def post(self, request, *args, **kwargs):
        template_name = 'login.html'
        success = 'home'
        form = LoginForm(data=request.POST)
        if form.is_valid():
            # フォームã‹ã‚‰'email'を読ã¿å–ã‚‹
            email = form.cleaned_data.get('email')
            # フォームã‹ã‚‰'password'を読ã¿å–ã‚‹
            password = form.cleaned_data.get('password')
            auth_object = EmailAuthBackend()
            user = auth_object.authenticate(email=email, password=password)
            if user is not None:
                #èªè¨¼å‡¦ç†
                login(request, user, backend='user.auth.EmailAuthBackend')
                redirect_to = request.POST.get('redirect_to')  #1 redirect_toã®å–å¾—
                if redirect_to is not None:
                    return redirect(redirect_to)
                else:
                    return redirect(success)
            else:
                return render(request, template_name, {'context': 'ログインã«å¤±æ•—ã—ã¾ã—ãŸ'})
    def get(self, request, *args, **kwargs):
        template_name = 'login.html'
        form = LoginForm(request.POST)
        redirect_to = request.GET.get('next')  #2 getパラメータã§å—ã‘å–ã£ãŸnextã‚’templateã¸æ¸¡ã™
        return render(request, template_name, {'context': 'get', 'redirect_to': redirect_to})
ã¾ãš#1ã®éƒ¨åˆ†ã§ã™ãŒã€postパラメータã§ãƒ­ã‚°ã‚¤ãƒ³å¾Œã®é·ç§»å…ˆã‚’å—ã‘å–ã£ã¦ã„ã¾ã™ã€‚ ã‚‚ã—æŒ‡å®šã•れã¦ã„ãªã‘れã°ã€å…±é€šã®ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆï¼ˆhome)ã«é·ç§»ã™ã‚‹ã‚ˆã†ã«ã—ã¾ã™ã€‚ パラメータをå—ã‘å–ã£ã¦ã„ã¾ã™ã®ã§ã€htmlã®formã‹ã‚‰ã€Œredirect_toã€ã¨ã„ã†å€¤ã‚’ 渡ã™å¿…è¦ãŒã‚りã¾ã™ã€‚ #2ã¯getパラメータã‹ã‚‰ã€Œnextã€ã¨ã„ã†å€¤ã‚’å–å¾—ã—ã¦ã„ã¾ã™ã€‚ 「nextã€ã¨ã„ã†ãƒ‘ラメータã¯Djangoã®èªè¨¼æ©Ÿèƒ½ã«çµ„ã¿è¾¼ã¾ã‚Œã¦ãŠã‚Š ãƒ­ã‚°ã‚¤ãƒ³ãŒå¿…è¦ãªé ˜åŸŸã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãŸéš›ã«getパラメータã«å‹æ‰‹ã«ã€Œnextã€ã¨ã„ã†ãƒ‘ラメータå㧠アクセスã—よã†ã¨ã—ã¦ã„ãŸãƒ‘ã‚¹ãŒæ ¼ç´ã•れã¾ã™ã€‚ ã“ã®ã€Œnextã€ã®å€¤ã‚’å—ã‘å–りã€login.htmlã«æ¸¡ã—ã¾ã™ã€‚ ãれã§ã¯æ¬¡ã«login.htmlã®ä¿®æ­£ã§ã™ã€‚
<body class="text-center">
<main class="form-signin">
  <form method="post">{% csrf_token %}
    <img class="mb-4" src="/docs/5.0/assets/brand/bootstrap-logo.svg" alt="Django" width="72" height="57">
    <h1 class="h3 mb-3 fw-normal">ログイン</h1>
      {{ context }}
    <label for="inputEmail" class="visually-hidden">メールアドレス</label>
    <input type="email" id="inputEmail" class="form-control" placeholder="メールアドレス" name = "email" required autofocus>
    <label for="inputPassword" class="visually-hidden">パスワード</label>
    <input type="password" id="inputPassword" class="form-control" placeholder="パスワード" name = "password" required>
    {% if redirect_to is not None %} <!-#3-修正点ã“ã“ã‹ã‚‰-->
      <input type="hidden" name="redirect_to" value="{{ redirect_to }}">
    {% endif %}  <!-#3-修正点ã“ã“ã¾ã§-->
    <div class="checkbox mb-3">
      <label>
        <input type="checkbox" value="remember-me"> 記憶ã™ã‚‹
      </label>
    </div>
    <button class="w-100 btn btn-lg btn-primary" type="submit">ログイン</button>
    <p class="mt-5 mb-3 text-muted">&amp;amp;copy; 2017-2021</p>
  </form>
</main>
</body>
修正点ã¯11行目ã®è¿½åР飲ã¿ã§ã™ã€‚ views.pyã‹ã‚‰æ¸¡ã•れãŸã€Œredirect_to ã€ã®å€¤ã‚’hiddenã«åŸ‹ã‚込んã§ã€å†åº¦views.pyã«æ¸¡ã—ã¦ã‚„りã¾ã™ã€‚ ã“ã†ã™ã‚‹ã“ã¨ã§ã€ãƒ­ã‚°ã‚¤ãƒ³ãŒæˆåŠŸã—ãŸå ´åˆã«å…ƒã€…アクセスã—よã†ã¨ã—ã¦ã„ãŸãƒšãƒ¼ã‚¸ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚

課題

ログイン後ã®ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆã¯getãƒ‘ãƒ©ãƒ¡ãƒ¼ã‚¿ã«æŒ‡å®šã—ãŸå€¤ã‚’利用ã—ã¦ã„ã¾ã™ã€‚
ãã®ãŸã‚ã€URLã‚’æ›¸ãæ›ãˆã‚‹ã“ã¨ã§
ログイン後ã«ä»–ã®ã‚µã‚¤ãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã•ã›ã‚‹ã“ã¨ã‚‚ã§ãã¦ã—ã¾ã„ã¾ã™ã€‚
ã“れを悪用ã•れるã¨ã€ä¾‹ãˆã°ä¸‹è¨˜ã®ã‚ˆã†ãªURLã‚’ã©ã“ã‹ã«æŽ²è¼‰ã•れã¦ã—ã¾ã†ã¨
ログイン後ã«å‹æ‰‹ã«yahooトップã«é£›ã°ã™ã“ã¨ã‚‚ã§ãã¦ã—ã¾ã„ã¾ã™ã€‚
https://ドメイン/?next=https://yahoo.co.jp

é·ç§»å…ˆãŒyahooトップãªã‚‰ã¾ã ã„ã„ã®ã§ã™ãŒã€ã“ã®é·ç§»å…ˆã‚’フィッシングサイトã«ã—ã¦
悪用ã•れるã“ã¨ãŒã‚りã¾ã™ã€‚
ã“ã®ã‚ˆã†ãªã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£å¯¾ç­–ã®ãŸã‚ã€ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆå…ˆã®URLをパラメータã‹ã‚‰å–å¾—ã—ã¦åˆ©ç”¨ã™ã‚‹å ´åˆã¯
ドメインをホワイトリストã¨ã—ã¦ç®¡ç†ã™ã‚‹ã‹ã€ç›¸å¯¾ãƒ‘スã—ã‹å—ã‘付ã‘ãªã„よã†ã«åˆ¶å¾¡ã‚’入れる必è¦ãŒã‚りã¾ã™ã€‚

Djangoãã®ä»–ã®è¨˜äº‹

Python
ã€Pyhon/Django】ログイン機能カスタマイズ
Python
Django
ã€Pyhon/Django】カスタムユーザã¨ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒ­ã‚°ã‚¤ãƒ³ï¼‘
Python
django
Python/Django é­é‡ã—ãŸã‚¨ãƒ©ãƒ¼é›†ã¨è§£æ±ºæ–¹æ³•
Django
django
Djangoã§adminã«ã‚«ã‚¹ã‚¿ãƒ ãƒ•ィルタ追加

 

コメントを残ã™