首先 django rest api 调用 returns request.user 作为 AnonymousUser 但进一步调用 return 正确的用户
First django rest api call returns request.user as AnonymousUser but further calls return proper user
现在我有一个 api 视图,需要知道哪个用户当前登录。当我尝试用登录用户调用它时;但是,它 returns 匿名用户。奇怪的是,如果我再次调用 api 视图,它 returns 就是正确的用户。我正在使用 django rest 框架和 JSON Web Tokens with simplejwt。现在 ReactJS 中的调用如下所示:
const fetchAuthorData = () => {
axiosInstance.get('authors/')
.then((res) => {
setAuthor(res.data)
}).catch((err) => {
fetchAuthorData()
})
fetchAuthorThreads()
fetchAuthorArticles()
}
但是,我知道一遍又一遍地递归调用它是非常危险的,因为如果用户在这个递归 api 调用之前实际上没有登录,即使我重定向,如果不知何故我的服务器失败了超载 api 个电话。有谁知道我该怎么做才能让我的 api 在第一次调用时正确识别用户是否已登录?
这是我的登录视图:
axiosInstance.post('author-auth/token/', {
email: formData.email,
password: formData.password,
}).then((response) => {
localStorage.setItem('access_token', response.data.access)
localStorage.setItem('refresh_token', response.data.refresh)
axiosInstance.defaults.headers['Authorization'] =
'JWT ' + localStorage.getItem('access_token')
history.push('/')
}).catch((err) => {
alert("Make Sure Login Credentials Are Correct")
})
这是错误的观点:
@api_view(['GET'])
def author(request):
print(request.user)
if request.user.is_authenticated:
author = request.user
serializer = AuthorAccessSerializer(author, many=False)
return Response(serializer.data)
else:
return HttpResponse(status=400)
在此,request.user是匿名用户,即使我已登录
这是另一个奇怪的视图的相似部分
@api_view(['GET', 'POST'])
def articles(request):
if request.method == 'GET':
category_name = request.query_params['category']
dash = request.query_params['dash']
#this part is very similiar and works for some reason
if dash == "True":
if request.user.is_authenticated:
articles = Article.objects.filter(author=request.user)
else:
return HttpResponse(status=401)
# *end part*
elif category_name:
try:
category = Category.objects.get(name__icontains=category_name)
except:
return HttpResponse(status=400, content="Category not found")
articles = Article.objects.filter(category=category)
else:
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
这是我的 axios 设置:
export const axiosInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
headers : {
Authorization: localStorage.getItem('access_token')
? 'JWT' + localStorage.getItem('access_token')
: null,
'Content-Type' : 'application/json',
accept : 'application/json'
}
})
这是我的休息框架和 JWT 身份验证设置:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(hours=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer', 'JWT'),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
ALLOWED_HOSTS=['127.0.0.1', 'http://localhost:5000']
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
)
同样,如果我继续调用同一个 api 调用,由于某种原因,它可以正常工作,不会更改任何授权 headers、令牌或任何其他内容,并且 request.user 可以正常工作我上面的第二种观点。谁能告诉我为什么会这样?
我认为,
1. localStorage.setItem('access_token', response.data.access)
2. localStorage.setItem('refresh_token', response.data.refresh)
3. axiosInstance.defaults.headers['Authorization'] =
'JWT ' + localStorage.getItem('access_token')
history.push('/')
登录代码可能会导致问题。
这些代码从不运行顺序;每个 javascript 运行 异步。
这意味着,您的 axiosInstance.defaults.headers
可能为空,因为第 1、2 和 3 行是同时执行的。换句话说,axiosInstance.defaults.headers
变为 null(因为 localStorage 上没有 access_token)然后,Js 从 response.data.access
.
设置 access_token
你最好在第 1 行和第 2 行之后使用 .then()
的 promise,
或在发出 http 请求时获取 axiosInstance 的授权。
现在我有一个 api 视图,需要知道哪个用户当前登录。当我尝试用登录用户调用它时;但是,它 returns 匿名用户。奇怪的是,如果我再次调用 api 视图,它 returns 就是正确的用户。我正在使用 django rest 框架和 JSON Web Tokens with simplejwt。现在 ReactJS 中的调用如下所示:
const fetchAuthorData = () => {
axiosInstance.get('authors/')
.then((res) => {
setAuthor(res.data)
}).catch((err) => {
fetchAuthorData()
})
fetchAuthorThreads()
fetchAuthorArticles()
}
但是,我知道一遍又一遍地递归调用它是非常危险的,因为如果用户在这个递归 api 调用之前实际上没有登录,即使我重定向,如果不知何故我的服务器失败了超载 api 个电话。有谁知道我该怎么做才能让我的 api 在第一次调用时正确识别用户是否已登录?
这是我的登录视图:
axiosInstance.post('author-auth/token/', {
email: formData.email,
password: formData.password,
}).then((response) => {
localStorage.setItem('access_token', response.data.access)
localStorage.setItem('refresh_token', response.data.refresh)
axiosInstance.defaults.headers['Authorization'] =
'JWT ' + localStorage.getItem('access_token')
history.push('/')
}).catch((err) => {
alert("Make Sure Login Credentials Are Correct")
})
这是错误的观点:
@api_view(['GET'])
def author(request):
print(request.user)
if request.user.is_authenticated:
author = request.user
serializer = AuthorAccessSerializer(author, many=False)
return Response(serializer.data)
else:
return HttpResponse(status=400)
在此,request.user是匿名用户,即使我已登录
这是另一个奇怪的视图的相似部分
@api_view(['GET', 'POST'])
def articles(request):
if request.method == 'GET':
category_name = request.query_params['category']
dash = request.query_params['dash']
#this part is very similiar and works for some reason
if dash == "True":
if request.user.is_authenticated:
articles = Article.objects.filter(author=request.user)
else:
return HttpResponse(status=401)
# *end part*
elif category_name:
try:
category = Category.objects.get(name__icontains=category_name)
except:
return HttpResponse(status=400, content="Category not found")
articles = Article.objects.filter(category=category)
else:
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
这是我的 axios 设置:
export const axiosInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
headers : {
Authorization: localStorage.getItem('access_token')
? 'JWT' + localStorage.getItem('access_token')
: null,
'Content-Type' : 'application/json',
accept : 'application/json'
}
})
这是我的休息框架和 JWT 身份验证设置:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(hours=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer', 'JWT'),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
ALLOWED_HOSTS=['127.0.0.1', 'http://localhost:5000']
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
)
同样,如果我继续调用同一个 api 调用,由于某种原因,它可以正常工作,不会更改任何授权 headers、令牌或任何其他内容,并且 request.user 可以正常工作我上面的第二种观点。谁能告诉我为什么会这样?
我认为,
1. localStorage.setItem('access_token', response.data.access)
2. localStorage.setItem('refresh_token', response.data.refresh)
3. axiosInstance.defaults.headers['Authorization'] =
'JWT ' + localStorage.getItem('access_token')
history.push('/')
登录代码可能会导致问题。
这些代码从不运行顺序;每个 javascript 运行 异步。
这意味着,您的 axiosInstance.defaults.headers
可能为空,因为第 1、2 和 3 行是同时执行的。换句话说,axiosInstance.defaults.headers
变为 null(因为 localStorage 上没有 access_token)然后,Js 从 response.data.access
.
你最好在第 1 行和第 2 行之后使用 .then()
的 promise,
或在发出 http 请求时获取 axiosInstance 的授权。