Django - 每个网址验证?

时间:2014-02-13 05:31:51

标签: django cordova django-authentication

我使用Django Web框架构建了一个Web应用程序。为了安全起见,我创建了一些中间件来确保每个URL都受密码保护。如果某个随机人员输入了webapp的URL,但未登录,则中间件会将他们踢到登录页面。

现在我正在尝试构建一个iOS应用程序,该应用程序将向运行较大Web应用程序的同一服务器发布和访问数据。想法是iOS应用程序将对服务器进行URL调用,服务器将吐出JSON数据。我正在使用PhoneGape构建应用程序,因此它在jQuery中的所有直接URL调用。

问题是,由于Web应用程序要求用户登录以执行任何操作,我需要一些方法来允许iOS应用程序发出数据请求,并让服务器以某种方式验证是否允许此请求,甚至虽然用户没有登录。基本上是按照每个URL验证的方式(但没有记录用户)。

我认为我最好的选择是使用相同的中间件,但应对其进行扩展,以便以/m/ios/开头的任何URL都以不同方式处理。从应用程序方面来说,我可以拥有它所请求的任何URL,它还会将用户的usernamepassword附加到该URL。因此,中间件可以刮掉用户名/密码并验证其有效用户,但不记录用户并简单地执行请求。

这是处理这种情况的合理方式吗?有没有更好的办法?

<小时/> 编辑我应该说,如果我正在做的事情是不恰当/不安全的话,我会非常乐意接近这一点


这是我的中间件文件,但它无法正常工作。验证有效,但最终调用URL未完成。

   from django.contrib.auth.views import login
   from django.contrib.auth import authenticate
   from django.http import HttpResponseRedirect, HttpResponse
   from django.utils import simplejson
   from django.core import serializers

   class SiteLogin:
       "This middleware requires a login for every view"
       def process_request(self, request):
          if request.path != '/accounts/login/' and request.user.is_anonymous():
              try:
                  url = request.path.split('/')[1]
                  url = url + '/' + request.path.split('/')[2] + '/'
                  print(url)
                  if url == 'm/ios/':
                      usr = request.GET['username']
                      psw = request.GET['password']
                      user = authenticate(username = usr, password = psw)
                      if user is not None:
                          if user.is_active:
                              # This line doesn't actually carry out the request
                              return login(request)
                      else:
                          d = {}
                          d['creds_good'] = "false"
                          json = simplejson.dumps(d)
                          GET = request.GET
                          callback = GET.get('callback')

                          if callback:
                              json = '%s(%s)' % (callback, json)

                          return HttpResponse(json, mimetype='application/json')
              except:
                  pass

              if request.POST:
                  return login(request)
              else:
                  return HttpResponseRedirect('/accounts/login/?next=%s' % request.path)

2 个答案:

答案 0 :(得分:1)

Django有一个login_required装饰器可供您使用。 您可以将网址映射到视图,以便某些网址需要登录而其他网址不需要

答案 1 :(得分:0)

我不会将用户名和密码放在请求的网址中。那些东西可以看成明文。这也让我相信你是ios app缓存了我的用户名和密码。这本身就是一种安全风险。

根据您当前的中间件逻辑,您仍在登录用户。看起来您正在为每个网址登录用户的ios请求,每个登录/网址创建一个新会话。

如果您的应用程序不支持http cookie,那么传递somesort的密钥或令牌是最好的方式,基本上与cookie相同但是手动执行。我会尝试利用django的会话和auth,尽可能多可能。在ios应用程序中,我会收集用户名和密码,然后立即致电登录。理想情况下,它会向ios应用程序返回一个持久的会话(https://docs.djangoproject.com/en/dev/topics/http/sessions/#django.contrib.sessions.backends.base.SessionBase.set_expiry),应用程序将仅存储返回的会话密钥。您将使用auth代替所有其他请求的用户名/密码凭据。只要电话保留会话密钥,电话就会失去接收,会话将不会消失,会话不会存在于服务器上的电话上。

如果可能的话,我会在之后的所有请求的标题中附加会话密钥(为了这个例子,我将调用标题DJANGO_SESSION_KEY),这样就可以在所有类型的请求中使用相同的位置(POST, GET,PUT等。)

然后我会扩展django的会话中间件并重写process_request函数。在我正在使用的django版本(1.5)中,我将更改在process_request函数中查找session_key的行。

class MySessionMiddleware(SessionMiddleware):                                                   
    def process_request(self, request):                                            
        engine = import_module(settings.SESSION_ENGINE)                            
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, request.META.get('HTTP_DJANGO_SESSION_KEY'))   
        request.session = engine.SessionStore(session_key)

然后我会在settings.py中使用这个自定义扩展会话中间件来代替django。

然后您的自定义中间件来到它,在请求中间件链的末尾定义。

def process_request(self, request):                                                
    if request.path != '/accounts/login/' and request.user.is_anonymous():         
        if request.META.HTTP_CONTENT_TYPE == 'application/json' or request.META.HTTP_ACCEPT == 'application/json':
            # return json error response                                           
        # return error redirect
相关问题