繁体   English   中英

Django - 使用电子邮件登录

[英]Django - Login with Email

我希望 django 通过电子邮件而不是用户名对用户进行身份验证。 一种方法是提供电子邮件值作为用户名值,但我不希望这样。 原因是,我有一个网址/profile/<username>/ ,因此我不能有一个网址/profile/abcd@gmail.com/

另一个原因是所有电子邮件都是唯一的,但有时会发生用户名已经被占用的情况。 因此,我将用户名自动创建为fullName_ID

我怎样才能改变让 Django 使用电子邮件进行身份验证?

这就是我创建用户的方式。

username = `abcd28`
user_email = `abcd@gmail.com`
user = User.objects.create_user(username, user_email, user_pass)

这就是我登录的方式。

email = request.POST['email']
password = request.POST['password']
username = User.objects.get(email=email.lower()).username
user = authenticate(username=username, password=password)
login(request, user)

除了首先获取用户名之外,还有其他登录方式吗?

您应该编写一个自定义身份验证后端。 像这样的东西会起作用:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

然后,在您的设置中将该后端设置为您的身份验证后端:

AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend']

更新 ModelBackend继承,因为它已经实现了get_user()之类的方法。

在此处查看文档: https ://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend

如果您正在开始一个新项目,django 强烈建议您设置自定义用户模型。 (见https://docs.djangoproject.com/en/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project

如果你这样做了,在你的用户模型中添加三行:

class MyUser(AbstractUser):
    USERNAME_FIELD = 'email'
    email = models.EmailField(_('email address'), unique=True) # changes email to unique and blank to false
    REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS

然后authenticate(email=email, password=password)工作,而authenticate(username=username, password=password)停止工作。

Django 3.x 的电子邮件身份验证

为了使用电子邮件/用户名和密码进行身份验证,而不是默认的用户名和密码身份验证,我们需要重写 ModelBackend 类的两个方法:authenticate() 和 get_user():

get_user 方法接受一个 user_id——它可以是用户名、数据库 ID 或其他任何东西,但必须对你的用户对象是唯一的——并返回一个用户对象或 None。 如果您没有将电子邮件保留为唯一键,则必须处理为 query_set 返回的多个结果。 在下面的代码中,通过从返回的列表中返回第一个用户来解决这个问题。

from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try: #to allow authentication through phone number or any other field, modify the below statement
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        except MultipleObjectsReturned:
            return User.objects.filter(email=username).order_by('id').first()
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None

默认情况下,AUTHENTICATION_BACKENDS 设置为:

['django.contrib.auth.backends.ModelBackend']

在 settings.py 文件中,在底部添加以下内容以覆盖默认值:

AUTHENTICATION_BACKENDS = ('appname.filename.EmailBackend',)

姜戈 4.0

有两种主要方法可以实现电子邮件身份验证,请注意以下几点:

  • 电子邮件在用户模型上应该是唯一的,以减少拼写错误和恶意使用。
  • 只有经过验证的电子邮件才应用于身份验证(如我们已发送验证电子邮件并且他们已单击验证链接)。
  • 我们应该经过验证的电子邮件地址发送电子邮件。

自定义用户模型

开始新项目时建议使用自定义用户模型,因为更改中间项目可能很棘手。

我们将添加一个email_verified字段以将电子邮件身份验证限制为具有经过验证的电子邮件地址的用户。

# app.models.py
from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    email_verified = models.BooleanField(default=False)

然后,我们将创建一个自定义身份验证后端,它将用给定的电子邮件地址替换用户名。

此后端将与显式设置email字段以及设置username段的身份验证表单一起使用。

# app.backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

UserModel = get_user_model()


class CustomUserModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get(
                Q(username__exact=username) | (Q(email__iexact=username) & Q(email_verified=True))
            )
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

然后我们修改我们的项目settings.py以使用我们的自定义用户模型和身份验证后端。

# project.settings.py

AUTH_USER_MODEL = "app.User"
AUTHENTICATION_BACKENDS = ["app.backends.CustomUserModelBackend"]

确保在migrate之前运行manage.py makemigrations并且第一次迁移包含这些设置。

扩展用户模型

虽然性能不如自定义User模型(需要辅助查询),但在现有项目中扩展现有User模型可能更好,并且根据登录流程和验证过程可能更受欢迎。

我们通过AUTH_USER_MODEL设置创建从EmailVerification到我们项目使用的任何User模型的一对一关系。

# app.models.py
from django.conf import settings
from django.db import models


class EmailVerification(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_query_name="verification"
    )
    verified = models.BooleanField(default=False)

我们还可以创建一个自定义管理员,其中包含我们的内联扩展。

# app.admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin

from .models import EmailVerification

UserModel = get_user_model()


class VerificationInline(admin.StackedInline):
    model = EmailVerification
    can_delete = False
    verbose_name_plural = 'verification'


class UserAdmin(BaseUserAdmin):
    inlines = (VerificationInline,)


admin.site.unregister(UserModel)
admin.site.register(UserModel, UserAdmin)

然后,我们创建一个类似于上面的后端,它只检查相关模型verified字段。

# app.backends.py
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

UserModel = get_user_model()


class ExtendedUserModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD, kwargs.get(UserModel.EMAIL_FIELD))
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get(
                Q(username__exact=username) | (Q(email__iexact=username) & Q(verification__verified=True))
            )
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

然后我们修改我们的项目settings.py以使用我们的身份验证后端。

# project.settings.py

AUTHENTICATION_BACKENDS = ["app.backends.ExtendedUserModelBackend"]

然后,您可以进行makemigrationsmigrate以向现有项目添加功能。

笔记

  • 如果用户名不区分大小写,则将Q(username__exact=username)更改为Q(username__iexact=username)
  • 在生产中防止新用户使用现有的经过验证的电子邮件地址进行注册。

我有一个类似的要求,用户名/电子邮件应该适用于用户名字段。如果有人正在寻找这样做的身份验证后端方式,请查看以下工作代码。如果您只需要电子邮件,您可以更改查询集。

from django.contrib.auth import get_user_model  # gets the user_model django  default or your own custom
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q


# Class to permit the athentication using email or username
class CustomBackend(ModelBackend):  # requires to define two functions authenticate and get_user

    def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()

        try:
            # below line gives query set,you can change the queryset as per your requirement
            user = UserModel.objects.filter(
                Q(username__iexact=username) |
                Q(email__iexact=username)
            ).distinct()

        except UserModel.DoesNotExist:
            return None

        if user.exists():
            ''' get the user object from the underlying query set,
            there will only be one object since username and email
            should be unique fields in your models.'''
            user_obj = user.first()
            if user_obj.check_password(password):
                return user_obj
            return None
        else:
            return None

    def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

还要在 settings.py 中添加 AUTHENTICATION_BACKENDS = ( 'path.to.CustomBackend', )

Django 2.X 的电子邮件和用户名身份验证

考虑到这是一个常见问题,这里有一个模仿Django 源代码的自定义实现,但它使用用户名或电子邮件对用户进行身份验证,不区分大小写,保持时间攻击保护并且不对非活动用户进行身份验证

from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q

class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None

永远记得在你的 settings.py 中添加正确的Authentication Backend

看来这样做的方法已经用 Django 3.0 更新了。

对我来说,一种工作方法是:

authentication.py # <-- 我把它放在一个应用程序中(在项目文件夹中与 settings.py 并没有工作

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User

class EmailBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

    def get_user(self, user_id):
        UserModel = get_user_model()
        try:
            return UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

然后将此添加到 settings.py 文件中

AUTHENTICATION_BACKENDS = (
    'appname.authentication.EmailBackend',
)

我为此创建了一个助手: function authenticate_user(email, password)

from django.contrib.auth.models import User


def authenticate_user(email, password):
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        return None
    else:
        if user.check_password(password):
            return user

    return None

class LoginView(View):
    template_name = 'myapp/login.html'

    def get(self, request):
        return render(request, self.template_name)

    def post(self, request):
        email = request.POST['email']
        password = request.POST['password']
        user = authenticate_user(email, password)
        context = {}

        if user is not None:
            if user.is_active:
                login(request, user)

                return redirect(self.request.GET.get('next', '/'))
            else:
                context['error_message'] = "user is not active"
        else:
            context['error_message'] = "email or password not correct"

        return render(request, self.template_name, context)

您应该自定义 ModelBackend 类。 我的简单代码:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

class YourBackend(ModelBackend):

  def authenticate(self, username=None, password=None, **kwargs):
    UserModel = get_user_model()
    if username is None:
        username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
        if '@' in username:
            UserModel.USERNAME_FIELD = 'email'
        else:
            UserModel.USERNAME_FIELD = 'username'

        user = UserModel._default_manager.get_by_natural_key(username)
    except UserModel.DoesNotExist:
        UserModel().set_password(password)
    else:
        if user.check_password(password) and self.user_can_authenticate(user):
            return user

settings.py文件中,添加:

AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']

使用 Django 2.x 的电子邮件和用户名进行身份验证

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

class EmailorUsernameModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

在 settings.py 中,添加以下行,

AUTHENTICATION_BACKENDS = ['appname.filename.EmailorUsernameModelBackend']
from django.contrib.auth.models import User

from django.db import Q

class EmailAuthenticate(object):

    def authenticate(self, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(email=username) | Q(username=username))
        except User.DoesNotExist:
            return None
        except MultipleObjectsReturned:
            return User.objects.filter(email=username).order_by('id').first()

        if user.check_password(password):
            return user
        return None

    def get_user(self,user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

然后在settings.py

AUTHENTICATION_BACKENDS = (
  'articles.backends.EmailAuthenticate',
)

其中articles 是我的django-app, backends.py是我的应用程序中的python 文件, EmailAuthenticate是我的backends.py文件中的身份验证后端类

2022 年 5 月更新:

该指令显示了如何使用“电子邮件”“密码”而不是“用户名”“密码”来设置身份验证,在该指令中, “用户名”被删除,我尽量不更改默认的 Django 设置

首先,运行以下命令来创建“帐户”应用程序

python manage.py startapp account

然后,将“account”应用程序设置为“INSTALLED_APPS” ,并在“settings.py”中设置AUTH_USER_MODEL = 'account.CustomUser' ,如下所示:

# "settings.py"

INSTALLED_APPS = [
    # ...
    "account", # Here
]

AUTH_USER_MODEL = 'account.CustomUser' # Here

然后,在“account”文件夹下创建 managers.py”,并在“managers.py”中创建“CustomUserManager”类扩展“UserManager”类,如下所示。 *只需将下面的代码复制并粘贴“managers.py”“managers.py”是使命令“python manage.py createsuperuser”正常工作而没有任何错误所必需的:

# "account/managers.py"

from django.contrib.auth.models import UserManager
from django.contrib.auth.hashers import make_password

class CustomUserManager(UserManager): # Here
   
    def _create_user(self, email, password, **extra_fields):
        
        if not email:
            raise ValueError("The given email must be set")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.password = make_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)

        if extra_fields.get("is_staff") is not True:
            raise ValueError("Superuser must have is_staff=True.")
        if extra_fields.get("is_superuser") is not True:
            raise ValueError("Superuser must have is_superuser=True.")

        return self._create_user(email, password, **extra_fields)

然后,创建扩展“AbstractUser”类“CustomUser”类并通过将其设置为“None”来删除“username”并将“email”设置为“unique=True”并将“email”设置为“USERNAME_FIELD”并将“CustomUserManager”类设置为“ account/models.py”中的“objects” ,如下所示。 *只需将以下代码复制并粘贴“account/models.py”

# "account/models.py"

from django.db import models
from django.contrib.auth.models import AbstractUser
from .managers import CustomUserManager

class CustomUser(AbstractUser):
    username = None # Here
    email = models.EmailField('email address', unique=True) # Here
    
    USERNAME_FIELD = 'email' # Here
    REQUIRED_FIELDS = []

    objects = CustomUserManager() # Here

    class Meta:
        verbose_name = "custom user"
        verbose_name_plural = "custom users"

或者,您也可以创建扩展“AbstractBaseUser”和“PermissionsMixin”类“CustomUser”类,如下所示。 *下面带有“AbstractBaseUser”和“PermissionsMixin”类的代码等同于上面带有“AbstractUser”类的代码,正如您所见,上面带有“AbstractUser”类的代码要少得多:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils import timezone
from .managers import CustomUserManager

class CustomUser(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField("first name", max_length=150, blank=True)
    last_name = models.CharField("last name", max_length=150, blank=True)
    email = models.EmailField('email address', unique=True)
    is_staff = models.BooleanField(
        "staff status",
        default=False,
        help_text="Designates whether the user can log into this admin site.",
    )
    is_active = models.BooleanField(
        "active",
        default=True,
        help_text=
            "Designates whether this user should be treated as active. "
            "Unselect this instead of deleting accounts."
        ,
    )
    date_joined = models.DateTimeField("date joined", default=timezone.now)

    USERNAME_FIELD = 'email'

    objects = CustomUserManager() # Here

然后,在“account”文件夹下创建 forms.py”并创建“CustomUserCreationForm”类扩展“UserCreationForm”类“CustomUserChangeForm”类扩展“UserChangeForm”类,并在“Meta”内部将“ CustomUser ”类设置为“model” “CustomUserCreationForm”中的“account/forms.py”中的“CustomUserChangeForm”类,如下所示。 *只需将以下代码复制并粘贴“forms.py”

# "account/forms.py"

from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser

class CustomUserCreationForm(UserCreationForm):

    class Meta:
        model = CustomUser
        fields = ('email',)

class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = CustomUser
        fields = ('email',)

然后,创建扩展“UserAdmin”类的“ CustomUserAdmin ”类,并将“CustomUserCreationForm”和“CustomUserChangeForm”类分别设置为“add_form”“form” ,并将“AdminPasswordChangeForm”类设置为“change_password_form” ,然后设置“CustomUser”和“CustomUserAdmin”类到“ account/admin.py”中的“admin.site.register()” ,如下所示。 *只需将以下代码复制并粘贴“account/admin.py”

from django.contrib import admin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from django.contrib.auth.forms import AdminPasswordChangeForm
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser

class CustomUserAdmin(UserAdmin):
    fieldsets = (
        (None, {"fields": ("password",)}),
        ("Personal info", {"fields": ("first_name", "last_name", "email")}),
        (
            "Permissions",
            {
                "fields": (
                    "is_active",
                    "is_staff",
                    "is_superuser",
                    "groups",
                    "user_permissions",
                ),
            },
        ),
        ("Important dates", {"fields": ("last_login", "date_joined")}),
    )
    add_fieldsets = (
        (
            None,
            {
                "classes": ("wide",),
                "fields": ("email", "password1", "password2"),
            },
        ),
    )
    add_form = CustomUserCreationForm # Here
    form = CustomUserChangeForm # Here
    change_password_form = AdminPasswordChangeForm # Here
    list_display = ("email", "first_name", "last_name", "is_staff")
    list_filter = ("is_staff", "is_superuser", "is_active", "groups")
    search_fields = ("first_name", "last_name", "email")
    ordering = ("email",)
    filter_horizontal = (
        "groups",
        "user_permissions",
    )

admin.site.register(CustomUser, CustomUserAdmin) # Here

然后,运行以下命令进行迁移和迁移:

python manage.py makemigrations && python manage.py migrate

然后,运行下面的命令来创建一个超级用户:

python manage.py createsuperuser

然后,运行以下命令来运行服务器:

python manage.py runserver 0.0.0.0:8000

然后,打开下面的网址:

http://localhost:8000/admin/login/

最后,您可以使用“电子邮件”“密码”登录,如下图所示:

在此处输入图像描述

这是“添加自定义用户”页面,如下所示:

在此处输入图像描述

对于 Django 2

username = get_object_or_404(User, email=data["email"]).username
        user = authenticate(
            request, 
            username = username, 
            password = data["password"]
        )
        login(request, user)

使用 Django 2.x 的电子邮件进行身份验证

def admin_login(request):
if request.method == "POST":
    email = request.POST.get('email', None)
    password = request.POST.get('password', None)
    try:
        get_user_name = CustomUser.objects.get(email=email)
        user_logged_in =authenticate(username=get_user_name,password=password)
        if user_logged_in is not None:
            login(request, user_logged_in)
            messages.success(request, f"WelcomeBack{user_logged_in.username}")
            return HttpResponseRedirect(reverse('backend'))
        else:
            messages.error(request, 'Invalid Credentials')
            return HttpResponseRedirect(reverse('admin_login'))
    except:
        messages.warning(request, 'Wrong Email')
        return HttpResponseRedirect(reverse('admin_login'))

else:
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse('backend'))
    return render(request, 'login_panel/login.html')

如果您创建了自定义数据库,则从那里验证您的电子邮件 ID 和密码。

  1. 使用models.objects.value_list('db_columnname').filter(db_emailname=textbox email)获取电子邮件 ID 和密码

2.assign in list 获取object_query_list

3.将列表转换为字符串

前任 :

  1. 获取Views.py中的 Html Email_idPassword

    u_email = request.POST.get('uemail')

    u_pass = request.POST.get('upass')

  2. 从数据库中获取电子邮件 ID 和密码

    Email = B_Reg.objects.values_list('B_Email',flat=True).filter(B_Email=u_email)

    Password = B_Reg.objects.values_list('Password',flat=True).filter(B_Email=u_email)

  3. Query值集中获取列表中的电子邮件 ID 和密码值

    Email_Value = Email[0]

    Password_Value=Password[0]

  4. 将列表转换为字符串

    string_email = ''.join(map(str, Email_Value))

    string_password = ''.join(map(str, Password_Value))

最后你的登录条件

if (string_email==u_email and string_password ==u_pass)

默认用户模型继承/扩展一个抽象类。 框架应该对一定数量的变化或变更宽容。

更简单的 hack 是执行以下操作:这是在虚拟环境中

  1. 转到您的 django 安装位置并找到Lib文件夹
  2. 导航到 django/contrib/auth/
  3. 找到并打开 models.py 文件。 找到 AbstractUser 类第 315 行

email 属性上的第 336 行添加 unique 并将其设置为 true

email = models.EmailField(_('email address'), blank=True,unique=True)

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
  1. 完成,进行迁移和迁移

这样做需要您自担风险,

很简单。 不需要任何额外的课程。

当您使用电子邮件创建和更新用户时,只需使用电子邮件设置用户名字段。

这样,当您验证用户名字段时,电子邮件的值将相同。

编码:

# Create
User.objects.create_user(username=post_data['email'] etc...)

# Update
user.username = post_data['email']
user.save()

# When you authenticate
user = authenticate(username=post_data['email'], password=password)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM