Django REST 框架 TokenAuthentication returns 匿名用户
Django REST framework TokenAuthentication returns anonymous user
如何在尝试登录时请求对象不返回匿名用户的情况下正确实施 DRF TokenAuthentication?
根据docs,当通过身份验证时,TokenAuthentication
对象提供request.user
这是Django用户实例和request.auth
这是令牌实例。但即使经过身份验证,request.user
returns 匿名用户。
我可能做错了什么?
客户请求:
//function to get token
export default function axiosConfig() {
// request header
const headers = {
"Content-Type": "application/json"
}
// Get token from local storage. Token is stored when user registers.
const token = localStorage.getItem("token");
if (token) headers["Authorisation"] = `Token ${token}`;
return headers;
}
Redux 动作
import axiosConfig from "../../utils/axiosConfig";
const config = axiosConfig
export const login = (email, password) => (dispatch, getState) => {
const body = { email, password };
// Change to absoulte path when deploying to production
axios
.post("http://localhost:8000/api/auth/login", body, config())
.then((res) => {
dispatch({
type: SIGN_IN_SUCCESFUL,
payload: res.data,
});
console.log(res);
})
.catch((err) => {
dispatch({
type: SIGN_IN_FAIL,
payload: err.response,
});
console.log(err.response.data, err.response.status);
});
};
Django
url:
from django.urls import path
from authentication.views import RegisterationView
from authentication.views import LoginView
from authentication.views import LogoutView
urlpatterns = [
path("auth/register", RegisterationView.as_view()),
path("auth/login", LoginView.as_view()),
path("auth/logout/<int:id>", LogoutView.as_view()),
]
序列化器:
LoginResponseSerializer
用于向客户端提供响应数据
class LoginSerializer(serializers.Serializer):
"""Login serializer"""
username = serializers.CharField()
password = serializers.CharField(required=True)
class LoginResponseSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = [
"id",
"username",
"first_name",
"last_name",
"email",
"is_active",
"is_staff",
]
read_only_fields = ["id", "is_active", "is_staff"]
查看:
class LoginView(APIView):
"""Login View"""
permision_classs = [permissions.AllowAny]
def post(self, request):
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
print(serializer.data) # Data is present
user = authenticate(request, **serializer.data) # Valid credentials. User object is returned.
response_serializer = LoginResponseSerializer(user)
if user is not None and login(request, user):
print(request.user) # User is anonymous
token, created_token = Token.objects.get_or_create(user_id=user.id)
if isinstance(created_token, Token):
token = created_token
return Response(
{
"user": response_serializer.data,
"status": {
"message": "user authenticated",
"code": status.HTTP_200_OK,
},
"token": token.key,
}
)
raise serializers.ValidationError(
"Invalid Username or Password. Please try again"
)
return Response(
{"error": serializer.errors, "status": status.HTTP_403_FORBIDDEN}
)
由于您使用的是令牌身份验证,因此对于每个请求,您的用户都将使用 header 中的令牌进行身份验证。
Django login()
在 SessionAuthentication 的情况下很有用。用户存储在 django 中的 session object 中,由 session cookie 标识。
在您看来,您不必调用登录方法。只是 return token
以及您想要的任何额外信息。并确保您在每个请求中发送此 token
以验证此用户。
编辑:
DRF 文档中关于 request.user
的说明是关于在 headers 中提供令牌的另一个视图中访问经过身份验证的用户。
如何在尝试登录时请求对象不返回匿名用户的情况下正确实施 DRF TokenAuthentication?
根据docs,当通过身份验证时,TokenAuthentication
对象提供request.user
这是Django用户实例和request.auth
这是令牌实例。但即使经过身份验证,request.user
returns 匿名用户。
我可能做错了什么?
客户请求:
//function to get token
export default function axiosConfig() {
// request header
const headers = {
"Content-Type": "application/json"
}
// Get token from local storage. Token is stored when user registers.
const token = localStorage.getItem("token");
if (token) headers["Authorisation"] = `Token ${token}`;
return headers;
}
Redux 动作
import axiosConfig from "../../utils/axiosConfig";
const config = axiosConfig
export const login = (email, password) => (dispatch, getState) => {
const body = { email, password };
// Change to absoulte path when deploying to production
axios
.post("http://localhost:8000/api/auth/login", body, config())
.then((res) => {
dispatch({
type: SIGN_IN_SUCCESFUL,
payload: res.data,
});
console.log(res);
})
.catch((err) => {
dispatch({
type: SIGN_IN_FAIL,
payload: err.response,
});
console.log(err.response.data, err.response.status);
});
};
Django
url:
from django.urls import path
from authentication.views import RegisterationView
from authentication.views import LoginView
from authentication.views import LogoutView
urlpatterns = [
path("auth/register", RegisterationView.as_view()),
path("auth/login", LoginView.as_view()),
path("auth/logout/<int:id>", LogoutView.as_view()),
]
序列化器:
LoginResponseSerializer
用于向客户端提供响应数据
class LoginSerializer(serializers.Serializer):
"""Login serializer"""
username = serializers.CharField()
password = serializers.CharField(required=True)
class LoginResponseSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = [
"id",
"username",
"first_name",
"last_name",
"email",
"is_active",
"is_staff",
]
read_only_fields = ["id", "is_active", "is_staff"]
查看:
class LoginView(APIView):
"""Login View"""
permision_classs = [permissions.AllowAny]
def post(self, request):
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
print(serializer.data) # Data is present
user = authenticate(request, **serializer.data) # Valid credentials. User object is returned.
response_serializer = LoginResponseSerializer(user)
if user is not None and login(request, user):
print(request.user) # User is anonymous
token, created_token = Token.objects.get_or_create(user_id=user.id)
if isinstance(created_token, Token):
token = created_token
return Response(
{
"user": response_serializer.data,
"status": {
"message": "user authenticated",
"code": status.HTTP_200_OK,
},
"token": token.key,
}
)
raise serializers.ValidationError(
"Invalid Username or Password. Please try again"
)
return Response(
{"error": serializer.errors, "status": status.HTTP_403_FORBIDDEN}
)
由于您使用的是令牌身份验证,因此对于每个请求,您的用户都将使用 header 中的令牌进行身份验证。
Django login()
在 SessionAuthentication 的情况下很有用。用户存储在 django 中的 session object 中,由 session cookie 标识。
在您看来,您不必调用登录方法。只是 return token
以及您想要的任何额外信息。并确保您在每个请求中发送此 token
以验证此用户。
编辑:
DRF 文档中关于 request.user
的说明是关于在 headers 中提供令牌的另一个视图中访问经过身份验证的用户。