我使用Django Web框架构建了一个Web应用程序。为了安全起见,我创建了一些中间件来确保每个URL都受密码保护。如果某个随机人员输入了webapp的URL,但未登录,则中间件会将他们踢到登录页面。
现在我正在尝试构建一个iOS应用程序,该应用程序将向运行较大Web应用程序的同一服务器发布和访问数据。想法是iOS应用程序将对服务器进行URL调用,服务器将吐出JSON数据。我正在使用PhoneGape构建应用程序,因此它在jQuery中的所有直接URL调用。
问题是,由于Web应用程序要求用户登录以执行任何操作,我需要一些方法来允许iOS应用程序发出数据请求,并让服务器以某种方式验证是否允许此请求,甚至虽然用户没有登录。基本上是按照每个URL验证的方式(但没有记录用户)。
我认为我最好的选择是使用相同的中间件,但应对其进行扩展,以便以/m/ios/
开头的任何URL都以不同方式处理。从应用程序方面来说,我可以拥有它所请求的任何URL,它还会将用户的username
和password
附加到该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)
答案 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