[Mobilar] 01 - Multiple Users: user registration, login and logout

R&D

一、调查取证

Ref: Many sites, one Wagtail: a detailed walkthrough

That's possible but Wagtail isn't set up to isolate a user that completely. From the post: "Users in this group will be able to see the other sites' content in the explorer menu, but they won't be able to create, edit, or delete any content in them." Clients probably wouldn't want to have to see other clients' junk, though. For the most part, Wagtail's user permissions are useful for isolating user's different responsibilities in a single large organization, not for letting multiple organizations share the same Wagtail install.

A better way to think about Wagtail's multi-site functionality is with a single organization which might have multiple brands like, say, Kellogg's cereal. You have lots of domains like frootloops.com, frostedflakes.com, frostedminiwheats.com, etc. but don't want to maintain a different server or CMS installation for each, so you could bring them all into a single Wagtail install with a different site tree for each. You could treat them as totally separate entities, each with different content types and templates, or you could have certain parts of the sites share content types, templates, and other features. It makes sense to combine some content given this setup, like an "About Kelloggs" page, for instance, so you're not making N updates for each brand -- just update once and have that content pulled in from Wagtail's snippets repository (or something).

 

From: slack of Wagtail by Cynthia Kiser

I had a somewhat similar requirement a few years ago and was able to use permissions to give each user access to only their pages - and now that there is a view permission for collections (as of 2.12), you can give each user their own collection for uploading images and documents.

目前练习使用的是 v2.5.1。

[问]

hi, @Cynthia Kiser, I see the latest version is 2.12rc1, and "Added a distinct 'choose' permission for images and documents" (Robert Rollins)
 this is a real new feature, but only for images and documents, not for pages.
My understanding is that, to implement Hadi's requirement,
(1) use permissions to give each user access to only their pages
(2) use the new feature of 2.12rc1 on images and documents.so that, each user will have their own pages, images, and documents. Right?

[答]

Yes that is correct. If you give each user edit permission on their profile page they can manage that page and no others. If you give them add permission on the profile page they can make subpages under their profile

[答]

Hi @Jeff! In the latest version of Wagtail, there is a "choose" permission that you can use to make a group of users able to only choose images/documents from specific collections. Wagtail isn't quite there yet in terms of 'fully isolated multi-tenancy' so some things might not be possible without patching. You may find the following issue helpful: https://github.com/wagtail/wagtail/issues/4288

 

Ref: Wagtail per page user permission

貌似通过 装饰器

 

Ref: use permissions to give each user access to only their pages

貌似通过 装饰器

 

How to modify wagtail CMS so that any user can post blog posts under their own blog

答案是不能,方案选型存在风险。

 

 

二、多品牌方案 

Django Tutorials【17个视频】

Multi-vendor Ecommerce Website using Django【Stein】

 

 

三、前后端分离

[Back-end]

Django Rest-framework【Token】

Ecommerce website using Django 3 and Vue.js | Django tutorial series【Stein】

 

[Front-end]

Build a YouTube bookmarking site with Vue.js【有点类似】

 

 

 

普通用户 - 注册

Ref: Python Django Tutorial: Full-Featured Web App Part 6 - User Registration 

文件 settings.py

INSTALLED_APPS = [
    'blog.apps.BlogConfig',
    'users.apps.UsersConfig',  # <---- 其实就是 文件夹路径,文件路径,类名
... ...

 

一、跨站请求伪造

网页 template/users/register.html

<form method="POST">{% csrf_token %}  # <---- 针对 form 会考虑的一个 feature

 

  • 是什么

Ref: 跨站请求伪造—CSRF

CSRF 攻击是攻击者借助受害者的 Cookie 骗取服务器的信任,在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击服务器,从而在并未授权的情况下执行在权限保护之下的操作。

 

  • Cookie 凭证

因为用户在网站登录后,这个网站服务端会在 Cookie 中会放一个凭证,这个凭证是后端用来验证用户身份的。

在发评论的时候,提交评论的请求会带上这个凭证,后端通过判断这个凭证,来确认是哪个用户。

 

  • 如何防止跨站请求伪造

CSRF能够攻击成功的本质是:重要操作的所有参数都是可以被攻击者猜测到的。

所以只要防止攻击者成功的构造一个伪造请求,就可以杜绝攻击了! 

 

 

二、路由设置 

from users import views as user_views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('register/', user_views.register, name='register'),
    path('', include('blog.urls')),
]

 

 

三、View 设置

这里没有涉及到 model,看来还是 封装了不少东西。

from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import UserRegisterForm


def register(request):
    if request.method == 'POST':
        # 其中,使用了 UserCreationForm 创建了 form。
        form = UserRegisterForm(request.POST)
        # 处理发来的 request.POST,后台注册成功后,则 is_valid = true
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            messages.success(request, f'Account created for {username}!')  # <---- 作为提示展示给用户
            return redirect('blog-home')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', {'form': form})

注册结果展示,tip的内容有点不同,但效果一样。

 

 

四、美化 form

第一步、安装 app package。

pip install django-crispy-forms

第二步、使用 app,settings.py 文件。

INSTALLED_APPS = [
    'blog.apps.BlogConfig',
    'users.apps.UsersConfig',
    'crispy_forms'  # <---- 


CRISPY_TEMPLATE_PACK = 'bootstrap4'

第三步、模板使用。

{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="content-section">
        <form method="POST">
            {% comment %} 防止跨站请求伪造 {% endcomment %}
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Join Today</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Sign Up</button>
            </div>
        </form>
        <div class="border-top pt-3">
            <small class="text-muted">
                Already Have An Account? <a class="ml-2" href="#">Sign In</a>
            </small>
        </div>
    </div>
{% endblock content %}

间接地 达到 css的效果。

{{ form.as_p }} 

更改为
{{ form
|crispy }}

1) {{ form.as_table }} 将表单渲染成一个表格元素,每个输入框作为一个<tr>标签

2) {{ form.as_p }} 将表单的每个输入框包裹在一个<p>标签内 tags

3) {{ form.as_ul }} 将表单渲染成一个列表元素,每个输入框作为一个<li>标签

 

 

 

普通用户 - 登录与退出

Ref: Python Django Tutorial: Full-Featured Web App Part 7 - Login and Logout System

 

一、登录

  • 点击登录按钮

自动验证是否登录成功等等。

{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="content-section">
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Log In</legend>
{{ form|crispy }} </fieldset> <div class="form-group"> <button class="btn btn-outline-info" type="submit">Login</button> # <---- </div> </form> <div class="border-top pt-3"> <small class="text-muted"> Need An Account? <a class="ml-2" href="{% url 'register' %}">Sign Up Now</a> </small> </div> </div> {% endblock content %}

 

  • 跳转到 user profile 界面

原来在 settings.py中设置。

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

CRISPY_TEMPLATE_PACK = 'bootstrap4'

# 登录的跳转控制 LOGIN_REDIRECT_URL
= 'blog-home' # 来源于 urls.py相关的路由定义中 LOGIN_URL = 'login'

 

 

二、页面权限

既然有了permission,user自己的页面只能自己访问,就涉及到 权限设置问题。

  • 登录后链接的改变

从 base.html 开始。这里,登录成功后,右上角的链接内容需要做出改变。

            <!-- Navbar Right Side -->
            <div class="navbar-nav">
              {% if user.is_authenticated %}
                <a class="nav-item nav-link" href="{% url 'profile' %}">Profile</a>
                <a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
              {% else %}
                <a class="nav-item nav-link" href="{% url 'login' %}">Login</a>
                <a class="nav-item nav-link" href="{% url 'register' %}">Register</a>
              {% endif %}
            </div>

 

  • 登录后才能进入的页面该如何显示

如果没登录,直接欲进入 profile,会自动切换到如下url。

也就是说:先login,成功后 next 就是profile的页面。

http://127.0.0.1:8000/login/?next=/profile/

所以,需要在 settings.py 中设置如下。

LOGIN_REDIRECT_URL = 'blog-home'
LOGIN_URL = 'login'

 

  • Profile 的实现

@login_required
def profile(request):
    return render(request, 'users/profile.html')

 

End.

posted @ 2021-01-26 22:01  郝壹贰叁  阅读(193)  评论(0编辑  收藏  举报