Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django视图所需的@login_decorator的反面是什么?_Django_Django Authentication - Fatal编程技术网

Django视图所需的@login_decorator的反面是什么?

Django视图所需的@login_decorator的反面是什么?,django,django-authentication,Django,Django Authentication,如果我想确保某个视图被列为具有公共访问权限,是否有一个与@public\u access相当的装饰器,它将与@login\u required相反,并明确指出该视图应始终可公开访问 我想到的一个用例是自动将“@csrf_emption”添加到所有公共视图中,并在代码中明确该视图应可公开访问。默认为“不需要登录”。如果您想注释视图不应被登录限制,那么您应该在docstring中这样做。不幸的是,Django中目前没有对此的内置支持,当意外忘记@login\u required时,您可能会暴露敏感信

如果我想确保某个视图被列为具有公共访问权限,是否有一个与@public\u access相当的装饰器,它将与@login\u required相反,并明确指出该视图应始终可公开访问


我想到的一个用例是自动将“@csrf_emption”添加到所有公共视图中,并在代码中明确该视图应可公开访问。

默认为“不需要登录”。如果您想注释视图不应被登录限制,那么您应该在docstring中这样做。

不幸的是,Django中目前没有对此的内置支持,当意外忘记
@login\u required
时,您可能会暴露敏感信息

以下是我的一个项目的解决方案:

中间件/security.py

def public(function):
    """Decorator for public views that do not require authentication
    """
    orig_func = function
    while isinstance(orig_func, partial):  # if partial - use original function for authorization
        orig_func = orig_func.func
    orig_func.is_public_view = True

    return function

def is_public(function):
    try:                                    # cache is found
        return function.is_public_view
    except AttributeError:                  # cache is not found
        result = function.__module__.startswith('django.') and not function.__module__.startswith('django.views.generic') # Avoid modifying admin and other built-in views

        try:                                # try to recreate cache
            function.is_public_view = result
        except AttributeError:
            pass

        return result


class NonpublicMiddleware(object):

    def process_view_check_logged(self, request, view_func, view_args, view_kwargs):
        return

    def process_view(self, request, view_func, view_args, view_kwargs):
        while isinstance(view_func, partial):  # if partial - use original function for authorization
            view_func = view_func.func

        request.public = is_public(view_func)
        if not is_public(view_func):
            if request.user.is_authenticated():     # only extended checks are needed
                return self.process_view_check_logged(request, view_func, view_args, view_kwargs)

            return self.redirect_to_login(request.get_full_path())  # => login page

    def redirect_to_login(self, original_target, login_url=settings.LOGIN_URL):
        return HttpResponseRedirect("%s?%s=%s" % (login_url, REDIRECT_FIELD_NAME, urlquote(original_target)))
MIDDLEWARE_CLASSES = (
    #...
    'middleware.security.NonpublicProfilefullMiddleware',
    #...
)
settings.py

def public(function):
    """Decorator for public views that do not require authentication
    """
    orig_func = function
    while isinstance(orig_func, partial):  # if partial - use original function for authorization
        orig_func = orig_func.func
    orig_func.is_public_view = True

    return function

def is_public(function):
    try:                                    # cache is found
        return function.is_public_view
    except AttributeError:                  # cache is not found
        result = function.__module__.startswith('django.') and not function.__module__.startswith('django.views.generic') # Avoid modifying admin and other built-in views

        try:                                # try to recreate cache
            function.is_public_view = result
        except AttributeError:
            pass

        return result


class NonpublicMiddleware(object):

    def process_view_check_logged(self, request, view_func, view_args, view_kwargs):
        return

    def process_view(self, request, view_func, view_args, view_kwargs):
        while isinstance(view_func, partial):  # if partial - use original function for authorization
            view_func = view_func.func

        request.public = is_public(view_func)
        if not is_public(view_func):
            if request.user.is_authenticated():     # only extended checks are needed
                return self.process_view_check_logged(request, view_func, view_args, view_kwargs)

            return self.redirect_to_login(request.get_full_path())  # => login page

    def redirect_to_login(self, original_target, login_url=settings.LOGIN_URL):
        return HttpResponseRedirect("%s?%s=%s" % (login_url, REDIRECT_FIELD_NAME, urlquote(original_target)))
MIDDLEWARE_CLASSES = (
    #...
    'middleware.security.NonpublicProfilefullMiddleware',
    #...
)
最后,查看代码:

from <projname>.middleware import publi

@public
def some_view(request):
    #...

# Login required is added automatically
def some_private_view(request):
    #...
from.middleware导入publi
@公开的
定义某些视图(请求):
#...
#自动添加所需的登录名
定义一些私有视图(请求):
#...

此外,您可能希望查看博客帖子,正如前面提到的海报一样,默认情况下不需要登录

然而,有时阻止登录用户查看某些视图是有用的——例如,登录用户能够使用站点的注册页面是没有意义的。在这种情况下,您可以根据现有的登录所需的decorator执行类似的操作

from django.contrib.auth.decorators import user_passes_test
from django.conf import settings

LOGGED_IN_HOME = settings.LOGGED_IN_HOME

def login_forbidden(function=None, redirect_field_name=None, redirect_to=LOGGED_IN_HOME):
    """
    Decorator for views that checks that the user is NOT logged in, redirecting
    to the homepage if necessary.
    """
    actual_decorator = user_passes_test(
        lambda u: not u.is_authenticated(),
        login_url=redirect_to,
        redirect_field_name=redirect_field_name
    )
    if function:
        return actual_decorator(function)
    return actual_decorator

有点晚了,但解决此问题的另一个简单方法是依赖另一个装饰器并添加lambda函数:

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.is_anonymous)
@权限类([permissions.AllowAny])

我使用所需的
login\u
decorator来保护整个应用程序,而不是一次一个视图。我的应用程序的主URL.py如下所示:

path('my_secret_app/', decorator_include(login_required, ('my_secret_app.urls', 'my_secret_app'))),
这非常有效,除非我的一个应用程序有一个视图需要公开

为了解决这个问题,我编写了自己的
login\u required
login\u not\u required
。我的
login\u required
基于django的
django.contrib.auth.decorators.login\u required
,但稍微修改了一下,以便在视图被标记为不需要登录时真正注意

我的项目名为
mysite

我的应用程序名为
My\u secret\u app

myu secret\u应用程序中的我的公共视图被称为
MyPublicView

我的整个解决方案如下所示:

path('my_secret_app/', decorator_include(login_required, ('my_secret_app.urls', 'my_secret_app'))),
mysite/lib.py

from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test

# A copy of django.contrib.auth.decorators.login_required that looks for login_not_required attr
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
    actual_decorator = user_passes_test(
        lambda u: u.is_authenticated,
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )

    if function:
        login_req = getattr(function, "login_required", True)

        if login_req:
            return actual_decorator(function)
        else:
            return function
    else:
        return actual_decorator

# Decorator to mark a view as not requiring login to access
def login_not_required(f):
    f.login_required = False
    return f
mysite/url.py

from .lib import login_required
path('my_secret_app/', decorator_include(login_required, ('my_secret_app.urls', 'my_secret_app'))),
my_secret_app/views.py:

from django.utils.decorators import method_decorator
from mysite.lib import login_not_required

class MyPublicView(View):
    @method_decorator(login_not_required)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request):
        ...

    def post(self, request, *args, **kwargs):
        ...
无论您是子类化
视图
列表视图
创建视图
更新视图
模板视图
,还是任何其他视图,您都应该能够做同样的事情。如果您使用函数作为视图,它也应该可以工作,尽管我没有尝试过:

@login_not_required
def MyPublicView(request):
    ...

我认为在某些情况下,如果用户登录,限制对某些功能的访问也是有用的。例如,不允许登录用户填写注册表。。。在这种情况下,您可以使用is_authenticated和is_anonymous的组合:使用“u.is_anonymous()”而不是“not u.is_authenticated()”。查看了解更多信息。见鬼:“编辑必须至少6个字符;这篇文章还有什么需要改进的吗?”该死的没有!
u.is_anonymous
中只缺少括号,因此示例不正确。示例正确且有效。你想在哪里加括号?哦,我查过文件了。你是对的,这是正确的,因为django 1.10+
是匿名的。但对于Django的早期版本,它将始终为您提供
True
,因为
是匿名的
was方法。没有任何解释-只有代码。我深入研究了如何导入permission_类,它似乎是rest_框架的一部分,我没有使用它。要么我错了,说几句关于从何处导入它以及在何处添加此代码的话会有所帮助,要么我是对的,这只在有人使用rest框架的情况下才相关,而在最初的问题中没有提到这一点