登录 Django 后重定向到下一步

问题描述 投票:0回答:6

当用户访问需要登录的网址时。视图装饰器重定向到登录页面。用户输入用户名和密码后,如何将用户重定向到他试图访问的页面(“下一个”)?

视图.py

def login_view(request):
    template = 'pos/login.html'
    form = LoginForm
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                messages.success(request, "You have logged in!")
                return redirect('home')
            else:
                messages.warning(request, "Your account is disabled!")
                return redirect('/login')
        else:
            messages.warning(request, "The username or password are not valid!")
            return redirect('/login')
    context = {'form': form}
    return render(request, template, context)

@login_required(redirect_field_name='next', login_url='/login')
def bar(request):
    template = 'pos/bar.html'
    drink = OrderItem.objects.filter(product__catgory__gt=1).order_by('-created')
    context = {'drink': drink}
    return render(request, template, context)

登录.html

<form action="/login" id="login_form" method="post" class="form-signin">
    {% csrf_token %}
    {{ form.as_p }}
    <button class="btn btn-lg btn-primary btn-block" type="submit" value="login">Sign in</button>
    <input type="hidden" name="next" value="{{next}}" />
</form>

url.py

     url(r'^login', views.login_view, name='login'),

表格.py

class LoginForm(AuthenticationForm):
    username = forms.CharField(label="Username", required=True, max_length=30,
                           widget=forms.TextInput(attrs={
                               'class': 'form-control',
                               'name': 'username'}))
    password = forms.CharField(label="Password", required=True, max_length=30,
                           widget=forms.PasswordInput(attrs={
                               'class': 'form-control',
                               'name': 'password'}))
django authentication
6个回答
27
投票

你可以尝试:

return redirect(self.request.GET.get('next'))

6
投票

编辑。我根据阅读评论中的文档和建议添加了 safe_redirect 函数。请批评指正:

def safe_redirect(request, next_url, fallback_url=settings.LOGIN_REDIRECT_URL):
    """
    Redirects safely to `next_url` or `fallback_url`. Ensures the target URL hosts match, 
    schemes are appropriate, and paths are resolvable within the project, mitigating 
    potential open redirect vulnerabilities.
    """
    next_url = iri_to_uri(next_url)
    try:
        if url_has_allowed_host_and_scheme(url=next_url, allowed_hosts={request.get_host()},
                                           require_https=request.is_secure()):
            resolve(next_url)
            return HttpResponseRedirect(next_url)
    except Resolver404:
        pass
    finally:
        return HttpResponseRedirect(fallback_url)

接受的答案不会检查重定向到外部站点的下一个参数。对于许多应用程序来说,这将是一个安全问题。 Django 以

django.utils.http.is_safe_url
函数的形式内置了该功能。可以这样使用:

from django.shortcuts import redirect
from django.utils.http import url_has_allowed_host_and_scheme
from django.conf import settings

def redirect_after_login(request):
    nxt = request.GET.get("next", None)
    if nxt is None:
        return redirect(settings.LOGIN_REDIRECT_URL)
    elif not url_has_allowed_host_and_scheme(
            url=nxt,
            allowed_hosts={request.get_host()},
            require_https=request.is_secure()):
        return redirect(settings.LOGIN_REDIRECT_URL)
    else:
        return redirect(nxt)

def my_login_view(request):
    # TODO: Check if its ok to login.
    # Then either safely redirect og go to default startpage.
    return redirect_after_login(request)

3
投票

您可以尝试在accounts/login.html模板中的提交按钮之前添加此输入字段

<input type="hidden" name="next" value="{{ request.GET.next }}"/>

1
投票

是的,Arun Ghosh 选项更好,但在找不到下一个值的情况下会导致异常。

因此我使用了这种方法。

try: return redirect(request.GET.get('next')) except TypeError: return HttpResponseRedirect(reverse("default_app:url_name"))

except Exception as e: return HttpResponseRedirect(reverse("default_app:url_name"))


0
投票

这实际上对我来说非常有用:

from django.shortcuts import redirect

def login(request):
    nxt = request.GET.get("next", None)
    url = '/admin/login/'

    if nxt is not None:
        url += '?next=' + nxt

return redirect(url)

如果前一个 URL 包含下一个 - 调用“登录”URL 并将前一个“下一个”附加到它。 然后,当您登录时,您将继续访问之前打算显示的下一个页面。

在我的项目中,我制作了以下适用于 Swagger 登录/注销的帮助程序:

def _redirect(request, url):
    nxt = request.GET.get("next", None)
    if nxt is not None:
        url += '?next=' + nxt
    return redirect(url)


def login(request):
    return _redirect(request, '/admin/login/')


def logout(request):
    return _redirect(request, '/admin/logout/')

-1
投票
path_redirect = request.get_full_path().split('?next=',1)
if '?next=' in request.get_full_path():# Redirecting After Login 
    return redirect(path_redirect[1])
else:
    return redirect('index')
© www.soinside.com 2019 - 2024. All rights reserved.