【问题标题】:django, using session in web for the first timedjango,第一次在 web 中使用 session
【发布时间】:2012-11-21 16:44:40
【问题描述】:

客户端访问登录视图,

//user is properly set here  
user = auth.authenticate(username=email, password=password)  
auth.login(request,user)  

请求登录视图的同一个客户端,请求另一个视图

// I expect the same user I logged in previously here. But I see anonymous user here.   
user = request.user

我不知道 Web 服务器如何准确识别来自同一用户的两个不同的 http 请求(因为 http 是无连接的)。但我知道session 是使它成为可能的概念。

我的settings.py 中有MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware',...)

还有什么我需要检查才能完成这项工作吗?

-编辑

我调试了一下,
django/contrib/auth/init:login 确实 request.session[SESSION_KEY] = user.id django/contrib/auth/init:get_user 尝试在下次运行时查找 request.session[SESSION_KEY] 并失败。

我需要了解 request.session 是什么。
我认为请求是客户端根据 http-request 发送的东西。(所以它不是持久的)

**以下是我的理解,如有错误请指正**

  1. 当用户登录时,服务器会为用户分配一个唯一的 id 并将其发送给用户。
  2. 服务器还将 id 的相关数据存储在某个持久性位置。
  3. 用户为每个后续的 http 请求发送唯一的 id。(这是 cookie)
  4. Django 使用给定的 id 查找在步骤 2(或在其他情况下)存储的数据。
  5. Django 将数据放入 request.session 并提供给查看。

我关注了Django, request.user is always Anonymous User

我怀疑这一切都是由于我从 http://www.micahcarrick.com/django-email-authentication.html 复制的自定义身份验证后端

我的第一个视图。

@csrf_exempt
def login(request):
    # import pdb                                                                                                                                                                                                                                                                
    # pdb.set_trace()                                                                                                                                                                                                                                                           

    email = request.POST['email']
    password = request.POST['password']

    user = auth.authenticate(username=email, password=password)
    # auth.logout(request)                                                                                                                                                                                                                                                      

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

        profile = user.get_profile()
        user_dict = profile.to_dict()

        jsonUser = json.dumps(user_dict, ensure_ascii=False, cls=DjangoJSONEncoder)
        return HttpResponse(jsonUser)
    else:
        raise Http404

我的第二个观点。

@csrf_exempt
def user_update(request):
    import pdb
    pdb.set_trace()

    user = request.user

=>  if not user.is_authenticated():
        raise Http404  // always ends up here

    print 'in user_update'
.......

MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # 取消注释下一行以获得简单的点击劫持保护:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware', )

我的后端

from django.contrib.auth.models import User, check_password

class EmailAuthBackend(object):
    """                                                                                                                                                                                                                                                                         
    Email Authentication Backend                                                                                                                                                                                                                                                

    Allows a user to sign in using an email/password pair rather than                                                                                                                                                                                                           
    a username/password pair.                                                                                                                                                                                                                                                   
    """

    supports_inactive_user = False

    def authenticate(self, username=None, password=None):
        """ Authenticate a user based on email address as the user name. """
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        """ Get a User object from the user_id. """
        print 'getting an user for user_id: ', user_id
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

【问题讨论】:

  • 你应该展示更多你的第二个视图。
  • 还有你的 full MIDDLEWARE_CLASSES 设置。
  • @DanielRoseman:我添加了它们。
  • cookie是否设置正确并存储在db中?
  • @maulik13:原来这确实是客户问题。我更改了我的代码,为所有请求共享一个 HttpClient 对象,它现在可以正常工作。不过感谢您的帮助!

标签: android django session login


【解决方案1】:

关于 http 是无状态的,你是对的。但是,使用 cookie 可以帮助您维护请求的状态。当您调用 login 函数时,Django 会将用户 ID(加密值)保存在名为 sessionid 的 cookie 中。所以下次你收到用户的请求时,浏览器也会在请求头中发送这个cookie。

如果您查看名为 *django_session* 的表,您应该会看到 session_key 与 cookie sessionid 具有相同值的条目。

AuthenticationMiddleware 跟踪用户身份验证并将用户对象分配给 request.user

SessionMiddleware 跟踪用户的会话数据

这就是 Django 跟踪用户及其会话的方式。

如果您真的想了解详细信息,可以查看身份验证中间件代码 (django.contrib.auth.middleware),尤其是 process_request 以检查用户是如何添加到请求对象中的。

也许这对调试您的问题很有用?

编辑:

基于从 cmets 对 Eugene 的帮助。

如果是与会话相关的问题(登录或会话数据),最好检查一下客户端的 cookie 是否设置正确。如果它是桌面浏览器,通过阅读 Firebug 的“Net”选项卡中的 http 标头,像 Firebug 这样的工具会很有帮助。

在 Eugene 的情况下,它是一个 Android 客户端,因此一种选择是调试 Django 中间件以检查 request.COOKIE 的值。如果您在 Django 端没有收到正确的 cookie,则 cookie 在客户端设置不正确。在浏览器上出现这种情况的原因之一是 cookie 可能被禁用。

因此,最好检查客户端设置以确保正确存储和发送 cookie。

【讨论】:

    猜你喜欢
    • 2014-05-27
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 2016-03-19
    • 2011-04-30
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多