最近在项目中需要将设备的数据上传到网站,决定使用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,找解决方案,以后这种态度要改,有时间的情况下还是要先浏览一下官方文档。