最近在项目中需要将设备的数据上传到网站,决定使用webservice。在如何调用需要身份认证的api上犯了愁,搜了无数文章都说是用Credentials,但就是不行,返回403,后来还是铁了心看官方文档,发现了问题。
#setting.py INSTALLED_APPS = ( #...... 'rest_framework', ) REST_FRAMEWORK = { # Use hyperlinked styles by default. # Only used if the `serializer_class` attribute is not set on a view. 'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.serializers.HyperlinkedModelSerializer', # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' ], #这里是关键 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ), 'PAGINATE_BY': 10 }
#models.py class DeviceValue(models.Model): """ Value sampled from device """ sample_time = models.DateTimeField(unique=True) value = models.FloatField()
from django.shortcuts import render from django.http import HttpRequest, HttpResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.decorators import action from rest_framework import viewsets from rest_framework.renderers import JSONRenderer from rest_framework.parsers import JSONParser from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.permissions import AllowAny, IsAuthenticatedOrReadOnly from models import DeviceValue import logging from serializers import DeviceValueSerializer # Create your views here. class JSONResponse(HttpResponse): """ An HttpResponse that renders its content into JSON. """ def __init__(self, data, **kwargs): content = JSONRenderer().render(data) kwargs['content_type'] = 'application/json' super(JSONResponse, self).__init__(content, **kwargs) class DeviceValueViewSet(viewsets.ModelViewSet): """ API endpoint that allows device value to be viewed or edited. """ queryset = DeviceValue.objects.all() serializer_class = DeviceValueSerializer #注意这里我将BasicAuthentication放在了SessionAuthentication前面,否则 #会先用SessionAuthentication认证,而这会造成C#的NetworkCredentials认证失败 authentication_classes = (BasicAuthentication, SessionAuthentication, ) permission_classes = (IsAuthenticatedOrReadOnly,) @csrf_exempt @action(methods=['POST', ]) def create_device_value(self, request): data = JSONParser().parse(request) serializer = DeviceValueSerializer(data=data) if serializer.is_valid(): serializer.save() return JSONResponse(serializer.data, status=201, ) return JSONResponse(serializer.errors, status=400, )
#serializers.py from rest_framework import serializers from models import DeviceValue class DeviceValueSerializer(serializers.ModelSerializer): class Meta: model = DeviceValue fields = ('sample_time', 'value')
#urls.py from django.conf.urls import patterns, include, url from rest_framework import routers from product_info import views from django.contrib import admin admin.autodiscover() router = routers.DefaultRouter() router.register(r'value', views.DeviceValueViewSet) urlpatterns = patterns('product_info.views', # Examples: url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), )
C#中这样:
var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.Credentials = new NetworkCredential(user, password); request.ContentType = @"application/json"; var json = "{\"sample_time\": \"2013-05-25 14:21:38+03:00\", \"value\": 20}"; using (var stream = new StreamWriter(request.GetRequestStream())) { stream.Write(json); stream.Flush(); } using (var response = (HttpWebResponse)request.GetResponse()) { Debug.WriteLine(response.StatusCode); using (var stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { var str = stream.ReadToEnd(); Debug.WriteLine(str); } } }
重点都注释了,希望给其它人帮助。
PS: 一直都偷懒,有问题先Google,stackoverflow,找解决方案,以后这种态度要改,有时间的情况下还是要先浏览一下官方文档。