如何向 Django / React 应用程序添加更改密码功能
How to add change password functionality to Django / React app
我正在尝试向 Django/React 应用程序添加更改密码功能。我正在努力寻找任何方法来完成这项工作。我正在使用 django-rest-auth 和 django-rest-framework。
我很乐意从 React 页面提交密码更改请求,或者将用户重定向到本机 Django 模板驱动的页面 - 离开我的 SPA,但可以让功能正常工作。
但是,更改密码页面需要用户登录,我无法从 React 应用中看到如何执行此操作。我已经使用自定义模板设置了 Django 页面,但是如果我从应用程序 link 到它,那么 URL 重定向到登录:
如果我将请求复制到 cURL 并在终端中 运行 它,我会看到此错误:
# api/urls.py
from django.urls import include, path
from django.contrib.auth import views
from django.conf.urls import include, url
urlpatterns = [
...
path('password_change/', views.PasswordChangeView.as_view(template_name='account/password_change.html'), name='password_change'),
]
account/password_change.html
{% extends 'account/base.html' %}
{% block body_block %}
<h1>Change your password</h1>
<form method="post" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
我登录到我的应用程序,然后导航到更改密码页面应该位于的位置:
http://localhost:8000/api/v1/password_change/
然后重定向到:
http://localhost:8000/accounts/login/?next=/api/v1/password_change/
我猜这是因为端点需要身份验证但未提供。但是,尽管我有一个存储的身份验证令牌,但我无法找到如何将其作为网络的一部分发送 link 并且以前使用重置密码的经验表明这不是 Django 从模板中寻找的令牌。
我找了很多年,但找不到任何有关如何向 React 应用程序添加更改密码的示例。这肯定是每个 React 应用程序都需要的东西吧?我缺少什么基本的东西?
编辑:感谢 Rik Schoonbeek 的回答,即 djang-rest-auth 提供的端点可以直接使用。不知何故,我在所有的困惑中都错过了这一点。如果它对其他人有帮助,这里是示例工作代码,它使用 JavaScript 获取和硬编码密码而不是来自表单的数据,只是为了演示该过程。
此代码还演示了检测提取命令中的错误,该命令的工作方式与您预期的不太一样。可能有更好的方法来做到这一点,但这至少给了你一个钩子。
工作代码:
export const changePassword = () => (dispatch) => {
const token = localStorage.getItem('jwtToken');
const data = {
'new_password1': 'othertext',
'new_password2': 'othertext',
'old_password': 'sometext'
};
var formData = new FormData();
// Push our data into our FormData object
for(var name in data) {
formData.append(name, data[name]);
}
const headers = {
'Authorization': `Token ${token}`,
};
return fetch('/api/v1/rest-auth/password/change/', {
headers,
'method': 'POST',
'body': formData,
})
.then(res => {
if(res.ok) {
console.log('successfully changed password');
return res.json();
} else {
console.log('error changing password');
}
})
.then(res => {
console.log('Change password res ', res);
});
};
而且很重要!将此添加到settings.py,否则无论旧密码是否正确,都会更改密码:
OLD_PASSWORD_FIELD_ENABLED = True
如果您希望用户在重置密码后保持登录状态,也请添加:
LOGOUT_ON_PASSWORD_CHANGE = False
如果您像我一样使用令牌身份验证,则可以通过在请求的 header 中发送令牌来授权用户更改密码。不过,您需要在标记前添加 "Token "(参见下面的示例)。
我就是这样做的,使用 axios 和令牌身份验证。
const response = await axios.post(
"http://127.0.0.1:8000/rest-auth/password/change/",
values,
{
headers: { Authorization: "Token " + this.props.loginToken }
}
);
密码更改端点需要发送以下数据:
- new_password1
- new_password2
- old_password
As explained here in the django-rest-auth docs
所以,我上面的 axios 请求中的 "values" 参数是一个包含这些值的 json。
我正在尝试向 Django/React 应用程序添加更改密码功能。我正在努力寻找任何方法来完成这项工作。我正在使用 django-rest-auth 和 django-rest-framework。
我很乐意从 React 页面提交密码更改请求,或者将用户重定向到本机 Django 模板驱动的页面 - 离开我的 SPA,但可以让功能正常工作。
但是,更改密码页面需要用户登录,我无法从 React 应用中看到如何执行此操作。我已经使用自定义模板设置了 Django 页面,但是如果我从应用程序 link 到它,那么 URL 重定向到登录:
如果我将请求复制到 cURL 并在终端中 运行 它,我会看到此错误:
# api/urls.py
from django.urls import include, path
from django.contrib.auth import views
from django.conf.urls import include, url
urlpatterns = [
...
path('password_change/', views.PasswordChangeView.as_view(template_name='account/password_change.html'), name='password_change'),
]
account/password_change.html
{% extends 'account/base.html' %}
{% block body_block %}
<h1>Change your password</h1>
<form method="post" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
我登录到我的应用程序,然后导航到更改密码页面应该位于的位置:
http://localhost:8000/api/v1/password_change/
然后重定向到:
http://localhost:8000/accounts/login/?next=/api/v1/password_change/
我猜这是因为端点需要身份验证但未提供。但是,尽管我有一个存储的身份验证令牌,但我无法找到如何将其作为网络的一部分发送 link 并且以前使用重置密码的经验表明这不是 Django 从模板中寻找的令牌。
我找了很多年,但找不到任何有关如何向 React 应用程序添加更改密码的示例。这肯定是每个 React 应用程序都需要的东西吧?我缺少什么基本的东西?
编辑:感谢 Rik Schoonbeek 的回答,即 djang-rest-auth 提供的端点可以直接使用。不知何故,我在所有的困惑中都错过了这一点。如果它对其他人有帮助,这里是示例工作代码,它使用 JavaScript 获取和硬编码密码而不是来自表单的数据,只是为了演示该过程。
此代码还演示了检测提取命令中的错误,该命令的工作方式与您预期的不太一样。可能有更好的方法来做到这一点,但这至少给了你一个钩子。
工作代码:
export const changePassword = () => (dispatch) => {
const token = localStorage.getItem('jwtToken');
const data = {
'new_password1': 'othertext',
'new_password2': 'othertext',
'old_password': 'sometext'
};
var formData = new FormData();
// Push our data into our FormData object
for(var name in data) {
formData.append(name, data[name]);
}
const headers = {
'Authorization': `Token ${token}`,
};
return fetch('/api/v1/rest-auth/password/change/', {
headers,
'method': 'POST',
'body': formData,
})
.then(res => {
if(res.ok) {
console.log('successfully changed password');
return res.json();
} else {
console.log('error changing password');
}
})
.then(res => {
console.log('Change password res ', res);
});
};
而且很重要!将此添加到settings.py,否则无论旧密码是否正确,都会更改密码:
OLD_PASSWORD_FIELD_ENABLED = True
如果您希望用户在重置密码后保持登录状态,也请添加:
LOGOUT_ON_PASSWORD_CHANGE = False
如果您像我一样使用令牌身份验证,则可以通过在请求的 header 中发送令牌来授权用户更改密码。不过,您需要在标记前添加 "Token "(参见下面的示例)。
我就是这样做的,使用 axios 和令牌身份验证。
const response = await axios.post(
"http://127.0.0.1:8000/rest-auth/password/change/",
values,
{
headers: { Authorization: "Token " + this.props.loginToken }
}
);
密码更改端点需要发送以下数据:
- new_password1
- new_password2
- old_password
As explained here in the django-rest-auth docs
所以,我上面的 axios 请求中的 "values" 参数是一个包含这些值的 json。