diff --git a/account/serializers.py b/account/serializers.py
index 4cda3ae0..f60e9cac 100644
--- a/account/serializers.py
+++ b/account/serializers.py
@@ -7,6 +7,7 @@ from .models import User
class UserLoginSerializer(serializers.Serializer):
username = serializers.CharField(max_length=30)
password = serializers.CharField(max_length=30)
+ captcha = serializers.CharField(required=False,min_length=4,max_length=4)
class UsernameCheckSerializer(serializers.Serializer):
@@ -22,6 +23,7 @@ class UserRegisterSerializer(serializers.Serializer):
real_name = serializers.CharField(max_length=30)
password = serializers.CharField(max_length=30, min_length=6)
email = serializers.EmailField(max_length=254)
+ captcha = serializers.CharField(max_length=4, min_length=4)
class UserChangePasswordSerializer(serializers.Serializer):
diff --git a/account/views.py b/account/views.py
index 4aa326a9..8a3414f3 100644
--- a/account/views.py
+++ b/account/views.py
@@ -5,15 +5,15 @@ from django.shortcuts import render
from django.db.models import Q
from rest_framework.views import APIView
-
+from rest_framework.response import Response
from utils.shortcuts import serializer_invalid_response, error_response, success_response, paginate
from utils.captcha import Captcha
from .decorators import login_required
from .models import User
from .serializers import (UserLoginSerializer, UsernameCheckSerializer,
- UserRegisterSerializer, UserChangePasswordSerializer,
- EmailCheckSerializer, UserSerializer, EditUserSerializer)
+ UserRegisterSerializer, UserChangePasswordSerializer,
+ EmailCheckSerializer, UserSerializer, EditUserSerializer)
class UserLoginAPIView(APIView):
@@ -26,6 +26,14 @@ class UserLoginAPIView(APIView):
serializer = UserLoginSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
+ user = User.objects.get(username=data["username"])
+ # 只有管理员才适用验证码登录
+ if user.admin_type > 0:
+ if not "captcha" in data:
+ return error_response(u"请填写验证码!")
+ captcha = Captcha(request)
+ if not captcha.check(data["captcha"]):
+ return error_response(u"验证码错误")
user = auth.authenticate(username=data["username"], password=data["password"])
# 用户名或密码错误的话 返回None
if user:
@@ -64,6 +72,9 @@ class UserRegisterAPIView(APIView):
serializer = UserRegisterSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
+ captcha = Captcha(request)
+ if not captcha.check(data["captcha"]):
+ return error_response(u"验证码错误")
try:
User.objects.get(username=data["username"])
return error_response(u"用户名已存在")
@@ -109,39 +120,35 @@ class UserChangePasswordAPIView(APIView):
class UsernameCheckAPIView(APIView):
- def post(self, request):
+ def get(self, request):
"""
- 检测用户名是否存在,存在返回True,不存在返回False
+ 检测用户名是否存在,存在返回状态码400,不存在返回200
---
- request_serializer: UsernameCheckSerializer
"""
- serializer = UsernameCheckSerializer(data=request.data)
- if serializer.is_valid():
+ username = request.GET.get("username", None)
+ if username:
try:
- User.objects.get(username=serializer.data["username"])
- return success_response(True)
+ User.objects.get(username=username)
+ return Response(status=400)
except User.DoesNotExist:
- return success_response(False)
- else:
- return serializer_invalid_response(serializer)
+ return Response(status=200)
+ return Response(status=200)
class EmailCheckAPIView(APIView):
- def post(self, request):
+ def get(self, request):
"""
- 检测邮箱是否存在,存在返回True,不存在返回False
+ 检测邮箱是否存在,存在返回状态码400,不存在返回200
---
- request_serializer: EmailCheckSerializer
"""
- serializer = EmailCheckSerializer(data=request.data)
- if serializer.is_valid():
+ email = request.GET.get("email", None)
+ if email:
try:
- User.objects.get(email=serializer.data["email"])
- return success_response(True)
+ User.objects.get(email=email)
+ return Response(status=400)
except User.DoesNotExist:
- return success_response(False)
- else:
- return serializer_invalid_response(serializer)
+ return Response(status=200)
+ return Response(status=200)
class UserAdminAPIView(APIView):
@@ -206,3 +213,19 @@ class UserInfoAPIView(APIView):
response_serializer: UserSerializer
"""
return success_response(UserSerializer(request.user).data)
+
+
+class AccountSecurityAPIView(APIView):
+ def get(self, request):
+ """
+ 判断用户登录是否需要验证码
+ ---
+ """
+ username = request.GET.get("username", None)
+ if username:
+ try:
+ User.objects.get(username=username, admin_type__gt=0)
+ except User.DoesNotExist:
+ return success_response({"applied_captcha": False})
+ return success_response({"applied_captcha": True})
+ return success_response({"applied_captcha": False})
diff --git a/oj/urls.py b/oj/urls.py
index d9373bb9..e1908712 100644
--- a/oj/urls.py
+++ b/oj/urls.py
@@ -4,7 +4,7 @@ from django.views.generic import TemplateView
from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView,
UserChangePasswordAPIView, EmailCheckAPIView,
- UserAdminAPIView, UserInfoAPIView)
+ UserAdminAPIView, UserInfoAPIView, AccountSecurityAPIView)
from announcement.views import AnnouncementAdminAPIView
@@ -115,4 +115,5 @@ urlpatterns = [
url(r'^api/submission/share/$', SubmissionShareAPIView.as_view(), name="submission_share_api"),
url(r'^captcha/$', "utils.captcha.views.show_captcha", name="show_captcha"),
+ url(r'^api/account_security_check/$', AccountSecurityAPIView.as_view(), name="account_security_check"),
]
diff --git a/static/src/js/app/oj/account/login.js b/static/src/js/app/oj/account/login.js
index 0a057627..32343c95 100644
--- a/static/src/js/app/oj/account/login.js
+++ b/static/src/js/app/oj/account/login.js
@@ -1,26 +1,31 @@
require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, csrfTokenHeader) {
+ var applied_captcha = false;
$('form').validator().on('submit', function (e) {
if (!e.isDefaultPrevented()) {
var username = $("#username").val();
var password = $("#password").val();
+ var ajaxData = {username: username, password: password};
+ if (applied_captcha) {
+ ajaxData.captcha = $("#captcha").val();
+ }
$.ajax({
beforeSend: csrfTokenHeader,
url: "/api/login/",
- data: {username: username, password: password},
+ data: ajaxData,
dataType: "json",
method: "post",
success: function (data) {
if (!data.code) {
//成功登陆
var ref = document.referrer;
- if(ref){
+ if (ref) {
// 注册页和本页的来源的跳转回首页,防止死循环
- if(ref.indexOf("register") > -1 || ref.indexOf("login") > -1){
+ if (ref.indexOf("register") > -1 || ref.indexOf("login") > -1) {
location.href = "/";
return;
}
// 判断来源,只有同域下才跳转
- if(ref.split("/")[2].split(":")[0] == location.hostname){
+ if (ref.split("/")[2].split(":")[0] == location.hostname) {
location.href = ref;
return;
}
@@ -28,6 +33,7 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
location.href = "/";
}
else {
+ refresh_captcha();
bsAlert(data.data);
}
}
@@ -35,5 +41,34 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
});
return false;
}
- })
+ });
+
+ $('#username').blur(function () {
+ if ($("#username").val()) {
+ $.ajax({
+ beforeSend: csrfTokenHeader,
+ url: "/api/account_security_check/?username=" + $("#username").val(),
+ method: "get",
+ success: function (data) {
+ if (!data.code) {
+ if (data.data.applied_captcha) {
+ $('#captcha-area').html('