mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 08:23:20 +00:00
完成两步验证的逻辑
This commit is contained in:
parent
0f8dedb540
commit
c297e4cf0f
@ -7,7 +7,7 @@ from .models import User, UserProfile
|
|||||||
class UserLoginSerializer(serializers.Serializer):
|
class UserLoginSerializer(serializers.Serializer):
|
||||||
username = serializers.CharField(max_length=30)
|
username = serializers.CharField(max_length=30)
|
||||||
password = serializers.CharField(max_length=30)
|
password = serializers.CharField(max_length=30)
|
||||||
captcha = serializers.CharField(min_length=4, max_length=4)
|
tfa_code = serializers.CharField(min_length=6, max_length=6, required=False)
|
||||||
|
|
||||||
|
|
||||||
class UsernameCheckSerializer(serializers.Serializer):
|
class UsernameCheckSerializer(serializers.Serializer):
|
||||||
|
@ -42,14 +42,23 @@ class UserLoginAPIView(APIView):
|
|||||||
serializer = UserLoginSerializer(data=request.data)
|
serializer = UserLoginSerializer(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
data = serializer.data
|
data = serializer.data
|
||||||
captcha = Captcha(request)
|
print data
|
||||||
if not captcha.check(data["captcha"]):
|
|
||||||
return error_response(u"验证码错误")
|
|
||||||
user = auth.authenticate(username=data["username"], password=data["password"])
|
user = auth.authenticate(username=data["username"], password=data["password"])
|
||||||
# 用户名或密码错误的话 返回None
|
# 用户名或密码错误的话 返回None
|
||||||
if user:
|
if user:
|
||||||
auth.login(request, user)
|
if not user.two_factor_auth:
|
||||||
return success_response(u"登录成功")
|
auth.login(request, user)
|
||||||
|
return success_response(u"登录成功")
|
||||||
|
|
||||||
|
# 没有输入两步验证的验证码
|
||||||
|
if user.two_factor_auth and "tfa_code" not in data:
|
||||||
|
return success_response("tfa_required")
|
||||||
|
|
||||||
|
if OtpAuth(user.tfa_token).valid_totp(data["tfa_code"]):
|
||||||
|
auth.login(request, user)
|
||||||
|
return success_response(u"登录成功")
|
||||||
|
else:
|
||||||
|
return error_response(u"验证码错误")
|
||||||
else:
|
else:
|
||||||
return error_response(u"用户名或密码错误")
|
return error_response(u"用户名或密码错误")
|
||||||
else:
|
else:
|
||||||
|
@ -135,6 +135,7 @@ urlpatterns = [
|
|||||||
url(r'^reset_password/$', TemplateView.as_view(template_name="oj/account/apply_reset_password.html"), name="apply_reset_password_page"),
|
url(r'^reset_password/$', TemplateView.as_view(template_name="oj/account/apply_reset_password.html"), name="apply_reset_password_page"),
|
||||||
url(r'^reset_password/t/(?P<token>\w+)/$', "account.views.reset_password_page", name="reset_password_page"),
|
url(r'^reset_password/t/(?P<token>\w+)/$', "account.views.reset_password_page", name="reset_password_page"),
|
||||||
url(r'^api/two_factor_auth/$', TwoFactorAuthAPIView.as_view(), name="two_factor_auth_api"),
|
url(r'^api/two_factor_auth/$', TwoFactorAuthAPIView.as_view(), name="two_factor_auth_api"),
|
||||||
|
url(r'^two_factor_auth/$', TemplateView.as_view(template_name="oj/account/two_factor_auth.html"), name="two_factor_auth_page"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,3 +118,13 @@ li.problem-tag {
|
|||||||
padding-top: 7.5px;
|
padding-top: 7.5px;
|
||||||
padding-bottom: 7.5px;
|
padding-bottom: 7.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#tfa-qrcode{
|
||||||
|
height: 40%;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tfa-area{
|
||||||
|
display: none;
|
||||||
|
}
|
@ -4,23 +4,31 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
|
|||||||
if (!e.isDefaultPrevented()) {
|
if (!e.isDefaultPrevented()) {
|
||||||
var username = $("#username").val();
|
var username = $("#username").val();
|
||||||
var password = $("#password").val();
|
var password = $("#password").val();
|
||||||
var captcha = $("#captcha").val();
|
var tfaCode = $("#tfa-code").val();
|
||||||
|
console.log(tfaCode);
|
||||||
|
if(tfaCode.length && tfaCode.length != 6){
|
||||||
|
bsAlert("验证码为六位数字");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
beforeSend: csrfTokenHeader,
|
beforeSend: csrfTokenHeader,
|
||||||
url: "/api/login/",
|
url: "/api/login/",
|
||||||
data: {username: username, password: password, captcha: captcha},
|
data: {username: username, password: password, tfa_code: tfaCode},
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
method: "post",
|
method: "post",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.code) {
|
if (!data.code) {
|
||||||
|
if(data.data == "tfa_required"){
|
||||||
|
$("#tfa-area").show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
function getLocationVal(id){
|
function getLocationVal(id){
|
||||||
var temp = unescape(location.search).split(id+"=")[1] || "";
|
var temp = unescape(location.search).split(id+"=")[1] || "";
|
||||||
return temp.indexOf("&")>=0 ? temp.split("&")[0] : temp;
|
return temp.indexOf("&")>=0 ? temp.split("&")[0] : temp;
|
||||||
}
|
}
|
||||||
var from = getLocationVal("__from");
|
var from = getLocationVal("__from");
|
||||||
if(from != ""){
|
if(from != ""){
|
||||||
console.log(from);
|
|
||||||
window.location.href = from;
|
window.location.href = from;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -28,7 +36,6 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
refresh_captcha();
|
|
||||||
bsAlert(data.data);
|
bsAlert(data.data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -40,11 +47,5 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
function refresh_captcha(){
|
|
||||||
$("#captcha-img")[0].src = "/captcha/?" + Math.random();
|
|
||||||
$("#captcha")[0].value = "";
|
|
||||||
}
|
|
||||||
$("#captcha-img").click(function(){
|
|
||||||
refresh_captcha();
|
|
||||||
});
|
|
||||||
});
|
});
|
27
static/src/js/app/oj/account/twoFactorAuth.js
Normal file
27
static/src/js/app/oj/account/twoFactorAuth.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
require(["jquery", "bsAlert", "csrfToken"], function ($, bsAlert, csrfTokenHeader) {
|
||||||
|
$("#tfa_submit").click(function(){
|
||||||
|
var code = $("#tfa_code").val();
|
||||||
|
if (code.length != 6){
|
||||||
|
bsAlert("验证码是6位数字");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
beforeSend: csrfTokenHeader,
|
||||||
|
url: "/api/two_factor_auth/",
|
||||||
|
data: {code: code},
|
||||||
|
dataType: "json",
|
||||||
|
method: "post",
|
||||||
|
success: function(data){
|
||||||
|
if(data.code){
|
||||||
|
bsAlert(data.data);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
bsAlert("两步验证开启成功");
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
@ -54,31 +54,32 @@
|
|||||||
//以下都是页面 script 标签引用的js
|
//以下都是页面 script 标签引用的js
|
||||||
announcement_0_pack: "app/admin/announcement/announcement",
|
announcement_0_pack: "app/admin/announcement/announcement",
|
||||||
userList_1_pack: "app/admin/user/userList",
|
userList_1_pack: "app/admin/user/userList",
|
||||||
problem_2_pack: "app/oj/problem/problem",
|
twoFactorAuth_2_pack: "app/oj/account/twoFactorAuth",
|
||||||
submissionList_3_pack: "app/admin/problem/submissionList",
|
problem_3_pack: "app/oj/problem/problem",
|
||||||
contestCountdown_4_pack: "app/oj/contest/contestCountdown",
|
submissionList_4_pack: "app/admin/problem/submissionList",
|
||||||
avatar_5_pack: "app/oj/account/avatar",
|
contestCountdown_5_pack: "app/oj/contest/contestCountdown",
|
||||||
addProblem_6_pack: "app/admin/problem/addProblem",
|
avatar_6_pack: "app/oj/account/avatar",
|
||||||
problem_7_pack: "app/admin/problem/problem",
|
addProblem_7_pack: "app/admin/problem/addProblem",
|
||||||
contestList_8_pack: "app/admin/contest/contestList",
|
problem_8_pack: "app/admin/problem/problem",
|
||||||
admin_9_pack: "app/admin/admin",
|
contestList_9_pack: "app/admin/contest/contestList",
|
||||||
login_10_pack: "app/oj/account/login",
|
admin_10_pack: "app/admin/admin",
|
||||||
applyResetPassword_11_pack: "app/oj/account/applyResetPassword",
|
login_11_pack: "app/oj/account/login",
|
||||||
addContest_12_pack: "app/admin/contest/addContest",
|
applyResetPassword_12_pack: "app/oj/account/applyResetPassword",
|
||||||
contestPassword_13_pack: "app/oj/contest/contestPassword",
|
addContest_13_pack: "app/admin/contest/addContest",
|
||||||
changePassword_14_pack: "app/oj/account/changePassword",
|
contestPassword_14_pack: "app/oj/contest/contestPassword",
|
||||||
monitor_15_pack: "app/admin/monitor/monitor",
|
changePassword_15_pack: "app/oj/account/changePassword",
|
||||||
editProblem_16_pack: "app/admin/contest/editProblem",
|
monitor_16_pack: "app/admin/monitor/monitor",
|
||||||
joinGroupRequestList_17_pack: "app/admin/group/joinGroupRequestList",
|
editProblem_17_pack: "app/admin/contest/editProblem",
|
||||||
group_18_pack: "app/oj/group/group",
|
joinGroupRequestList_18_pack: "app/admin/group/joinGroupRequestList",
|
||||||
contestProblemList_19_pack: "app/admin/contest/contestProblemList",
|
group_19_pack: "app/oj/group/group",
|
||||||
editProblem_20_pack: "app/admin/problem/editProblem",
|
contestProblemList_20_pack: "app/admin/contest/contestProblemList",
|
||||||
register_21_pack: "app/oj/account/register",
|
editProblem_21_pack: "app/admin/problem/editProblem",
|
||||||
groupDetail_22_pack: "app/admin/group/groupDetail",
|
register_22_pack: "app/oj/account/register",
|
||||||
editContest_23_pack: "app/admin/contest/editContest",
|
groupDetail_23_pack: "app/admin/group/groupDetail",
|
||||||
resetPassword_24_pack: "app/oj/account/resetPassword",
|
editContest_24_pack: "app/admin/contest/editContest",
|
||||||
group_25_pack: "app/admin/group/group",
|
resetPassword_25_pack: "app/oj/account/resetPassword",
|
||||||
settings_26_pack: "app/oj/account/settings"
|
group_26_pack: "app/admin/group/group",
|
||||||
|
settings_27_pack: "app/oj/account/settings"
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
avalon: {
|
avalon: {
|
||||||
@ -96,79 +97,82 @@
|
|||||||
name: "userList_1_pack"
|
name: "userList_1_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "problem_2_pack"
|
name: "twoFactorAuth_2_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "submissionList_3_pack"
|
name: "problem_3_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "contestCountdown_4_pack"
|
name: "submissionList_4_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "avatar_5_pack"
|
name: "contestCountdown_5_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "addProblem_6_pack"
|
name: "avatar_6_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "problem_7_pack"
|
name: "addProblem_7_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "contestList_8_pack"
|
name: "problem_8_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "admin_9_pack"
|
name: "contestList_9_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "login_10_pack"
|
name: "admin_10_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "applyResetPassword_11_pack"
|
name: "login_11_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "addContest_12_pack"
|
name: "applyResetPassword_12_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "contestPassword_13_pack"
|
name: "addContest_13_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "changePassword_14_pack"
|
name: "contestPassword_14_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "monitor_15_pack"
|
name: "changePassword_15_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "editProblem_16_pack"
|
name: "monitor_16_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "joinGroupRequestList_17_pack"
|
name: "editProblem_17_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "group_18_pack"
|
name: "joinGroupRequestList_18_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "contestProblemList_19_pack"
|
name: "group_19_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "editProblem_20_pack"
|
name: "contestProblemList_20_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register_21_pack"
|
name: "editProblem_21_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "groupDetail_22_pack"
|
name: "register_22_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "editContest_23_pack"
|
name: "groupDetail_23_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "resetPassword_24_pack"
|
name: "editContest_24_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "group_25_pack"
|
name: "resetPassword_25_pack"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "settings_26_pack"
|
name: "group_26_pack"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "settings_27_pack"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
optimizeCss: "standard",
|
optimizeCss: "standard",
|
||||||
|
@ -56,31 +56,32 @@ var require = {
|
|||||||
//以下都是页面 script 标签引用的js
|
//以下都是页面 script 标签引用的js
|
||||||
announcement_0_pack: "app/admin/announcement/announcement",
|
announcement_0_pack: "app/admin/announcement/announcement",
|
||||||
userList_1_pack: "app/admin/user/userList",
|
userList_1_pack: "app/admin/user/userList",
|
||||||
problem_2_pack: "app/oj/problem/problem",
|
twoFactorAuth_2_pack: "app/oj/account/twoFactorAuth",
|
||||||
submissionList_3_pack: "app/admin/problem/submissionList",
|
problem_3_pack: "app/oj/problem/problem",
|
||||||
contestCountdown_4_pack: "app/oj/contest/contestCountdown",
|
submissionList_4_pack: "app/admin/problem/submissionList",
|
||||||
avatar_5_pack: "app/oj/account/avatar",
|
contestCountdown_5_pack: "app/oj/contest/contestCountdown",
|
||||||
addProblem_6_pack: "app/admin/problem/addProblem",
|
avatar_6_pack: "app/oj/account/avatar",
|
||||||
problem_7_pack: "app/admin/problem/problem",
|
addProblem_7_pack: "app/admin/problem/addProblem",
|
||||||
contestList_8_pack: "app/admin/contest/contestList",
|
problem_8_pack: "app/admin/problem/problem",
|
||||||
admin_9_pack: "app/admin/admin",
|
contestList_9_pack: "app/admin/contest/contestList",
|
||||||
login_10_pack: "app/oj/account/login",
|
admin_10_pack: "app/admin/admin",
|
||||||
applyResetPassword_11_pack: "app/oj/account/applyResetPassword",
|
login_11_pack: "app/oj/account/login",
|
||||||
addContest_12_pack: "app/admin/contest/addContest",
|
applyResetPassword_12_pack: "app/oj/account/applyResetPassword",
|
||||||
contestPassword_13_pack: "app/oj/contest/contestPassword",
|
addContest_13_pack: "app/admin/contest/addContest",
|
||||||
changePassword_14_pack: "app/oj/account/changePassword",
|
contestPassword_14_pack: "app/oj/contest/contestPassword",
|
||||||
monitor_15_pack: "app/admin/monitor/monitor",
|
changePassword_15_pack: "app/oj/account/changePassword",
|
||||||
editProblem_16_pack: "app/admin/contest/editProblem",
|
monitor_16_pack: "app/admin/monitor/monitor",
|
||||||
joinGroupRequestList_17_pack: "app/admin/group/joinGroupRequestList",
|
editProblem_17_pack: "app/admin/contest/editProblem",
|
||||||
group_18_pack: "app/oj/group/group",
|
joinGroupRequestList_18_pack: "app/admin/group/joinGroupRequestList",
|
||||||
contestProblemList_19_pack: "app/admin/contest/contestProblemList",
|
group_19_pack: "app/oj/group/group",
|
||||||
editProblem_20_pack: "app/admin/problem/editProblem",
|
contestProblemList_20_pack: "app/admin/contest/contestProblemList",
|
||||||
register_21_pack: "app/oj/account/register",
|
editProblem_21_pack: "app/admin/problem/editProblem",
|
||||||
groupDetail_22_pack: "app/admin/group/groupDetail",
|
register_22_pack: "app/oj/account/register",
|
||||||
editContest_23_pack: "app/admin/contest/editContest",
|
groupDetail_23_pack: "app/admin/group/groupDetail",
|
||||||
resetPassword_24_pack: "app/oj/account/resetPassword",
|
editContest_24_pack: "app/admin/contest/editContest",
|
||||||
group_25_pack: "app/admin/group/group",
|
resetPassword_25_pack: "app/oj/account/resetPassword",
|
||||||
settings_26_pack: "app/oj/account/settings",
|
group_26_pack: "app/admin/group/group",
|
||||||
|
settings_27_pack: "app/oj/account/settings"
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
avalon: {
|
avalon: {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<li class="list-group-header">通用设置</li>
|
<li class="list-group-header">通用设置</li>
|
||||||
<li class="list-group-item"><a href="/account/settings/">个人信息</a></li>
|
<li class="list-group-item"><a href="/account/settings/">个人信息</a></li>
|
||||||
<li class="list-group-item active"><a href="/account/settings/avatar/">更换头像</a></li>
|
<li class="list-group-item active"><a href="/account/settings/avatar/">更换头像</a></li>
|
||||||
|
<li class="list-group-item"><a href="/two_factor_auth/">两步验证</a></li>
|
||||||
<li class="list-group-item"><a href="/change_password/">修改密码</a></li>
|
<li class="list-group-item"><a href="/change_password/">修改密码</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<li class="list-group-header">通用设置</li>
|
<li class="list-group-header">通用设置</li>
|
||||||
<li class="list-group-item"><a href="/account/settings/">个人信息</a></li>
|
<li class="list-group-item"><a href="/account/settings/">个人信息</a></li>
|
||||||
<li class="list-group-item"><a href="/account/settings/avatar/">更换头像</a></li>
|
<li class="list-group-item"><a href="/account/settings/avatar/">更换头像</a></li>
|
||||||
|
<li class="list-group-item"><a href="/two_factor_auth/">两步验证</a></li>
|
||||||
<li class="list-group-item active"><a href="/change_password/">修改密码</a></li>
|
<li class="list-group-item active"><a href="/change_password/">修改密码</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,22 +11,21 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="username">用户名</label>
|
<label for="username">用户名</label>
|
||||||
<input type="text" class="form-control input-lg" id="username" name="username" maxlength="30"
|
<input type="text" class="form-control input-lg" id="username" name="username" maxlength="30"
|
||||||
data-error="请填写用户名" placeholder="用户名" autofocus required>
|
data-error="请填写用户名" placeholder="用户名" autofocus required autocomplete="off">
|
||||||
|
|
||||||
<div class="help-block with-errors"></div>
|
<div class="help-block with-errors"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password">密码</label>
|
<label for="password">密码</label>
|
||||||
<input type="password" class="form-control input-lg" id="password" name="password" maxlength="30"
|
<input type="password" class="form-control input-lg" id="password" name="password" maxlength="30"
|
||||||
data-error="请填写密码" placeholder="密码" required>
|
data-error="请填写密码" placeholder="密码" required autocomplete="off">
|
||||||
|
|
||||||
<div class="help-block with-errors"></div>
|
<div class="help-block with-errors"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="captcha-area">
|
<div class="form-group" id="tfa-area">
|
||||||
<label for="captcha">验证码</label> <img src="/captcha/" id="captcha-img"><small>
|
<label for="captcha">两步验证</label>
|
||||||
<p></p></small>
|
<input type="text" class="form-control input-lg" id="tfa-code" name="tfa-code"
|
||||||
<input type="text" class="form-control input-lg" id="captcha" name="captcha"
|
placeholder="两步验证验证码" maxlength="6" data-error="请填写两步验证验证码" required autocomplete="off">
|
||||||
placeholder="验证码" maxlength="4" data-error="请填写验证码" required>
|
|
||||||
<div class="help-block with-errors"></div>
|
<div class="help-block with-errors"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<li class="list-group-header">通用设置</li>
|
<li class="list-group-header">通用设置</li>
|
||||||
<li class="list-group-item active"><a href="/account/settings/">个人信息</a></li>
|
<li class="list-group-item active"><a href="/account/settings/">个人信息</a></li>
|
||||||
<li class="list-group-item"><a href="/account/settings/avatar/">更换头像</a></li>
|
<li class="list-group-item"><a href="/account/settings/avatar/">更换头像</a></li>
|
||||||
|
<li class="list-group-item"><a href="/two_factor_auth/">两步验证</a></li>
|
||||||
<li class="list-group-item"><a href="/change_password/">修改密码</a></li>
|
<li class="list-group-item"><a href="/change_password/">修改密码</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
41
template/src/oj/account/two_factor_auth.html
Normal file
41
template/src/oj/account/two_factor_auth.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{% extends "oj_base.html" %}
|
||||||
|
{% block title %}
|
||||||
|
两步验证
|
||||||
|
{% endblock %}
|
||||||
|
{% block body %}
|
||||||
|
<div class="container main">
|
||||||
|
|
||||||
|
<div class="col-lg-2">
|
||||||
|
<ul class="list-group">
|
||||||
|
<li class="list-group-header">通用设置</li>
|
||||||
|
<li class="list-group-item"><a href="/account/settings/">个人信息</a></li>
|
||||||
|
<li class="list-group-item"><a href="/account/settings/avatar/">更换头像</a></li>
|
||||||
|
<li class="list-group-item active"><a href="/two_factor_auth/">两步验证</a></li>
|
||||||
|
<li class="list-group-item"><a href="/change_password/">修改密码</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-8">
|
||||||
|
{% if not request.user.two_factor_auth %}
|
||||||
|
<h3>扫描二维码开启两步验证</h3>
|
||||||
|
<img src="/api/two_factor_auth/" id="tfa-qrcode">
|
||||||
|
|
||||||
|
<div class="form-inline">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="tfa_code">验证码</label>
|
||||||
|
<input type="text" maxlength="6" class="form-control" id="tfa_code"
|
||||||
|
placeholder="输入 app 上显示的验证码">
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-primary" id="tfa_submit">确定</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-success" role="alert">两步验证已经开启</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js_block %}
|
||||||
|
<script src="/static/js/app/oj/account/twoFactorAuth.js"></script>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user