pip install django_redis
进入acapp/acapp/settings.py,添加:
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
},
}
USER_AGENTS_CACHE = 'default'
sudo redis-server /etc/redis/redis.conf
python3 manage.py shell
from django.core.cache import cache
4.1查找redis数据库所有key 支持正则表达式
cache.keys("*") 查
4.2插入键值对
cache.set(‘ybz’,1,None)# None 表示存活时间为永久/s 增和改
cache.set(‘ybz’,[21,‘coding’],10)# None 表示存活时间为10s
4.3某key值是否存在
cache.has_key(‘xxx’) 查
4.4查询某个关键字的值
cache.get(‘xxx’) 查
4.5删除某个关键字
cache.delete(‘xxx’) 删
参考链接:
https://www.acwing.com/blog/content/12466/
https://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
client web acwing
首先client端点击第三方登录
通过web服务器向acwing发送请求和appid返回授权确认界面(acwing端界面)
若用户同意授权,则acwing将授权码code发送给web服务器
web服务器接收到以后将自己的appid的appsecret以及授权码code发送给acwing 申请授权令牌
acwing发现信息没有问题,则发送给web服务器一个授权令牌 access-token和openid(用户识别码)
web服务器用授权令牌和openid发送给acwing申请用户名和头像信息
acwing发现没有问题就会返回用户名和头像给web服务器,web服务器就会保存下来 重定向到游戏界面
( web向acwing请求的code和access-token都是2个小时限制)
若不同意 不会发生重定向
# 先扩充player表的属性 openid
在acapp/game/models/player的player.py加入
openid=models.CharField(default='',max_length=50,blank=True,null=True)
# 保存到数据库
python3 manage.py makemigrations
python3 manage.py migrate
进入acapp/game/views/settings创建acwing文件夹,同时在acwing文件夹中创建__init__.py,acapp和web文件夹
在web文件夹中创建apply_code.py与receive_code.py
apply_code.py:
from django.http import JsonResponse
from urllib.parse import quote
from random import randint
from django.core.cache import cache
def get_state():
res = ""
for i in range(8):
res += str(randint(0, 9))
return res
def apply_code(request):
appid = "273"
redirect_uri = quote("https://app273.acapp.acwing.com.cn/settings/acwing/web/receive_code/")
scope = "userinfo"
state = get_state()
cache.set(state, True, 7200) # 有效期2小时
apply_code_url = "https://www.acwing.com/third_party/api/oauth2/web/authorize/"
return JsonResponse({
'result': "success",
'apply_code_url': apply_code_url + "?appid=%s&redirect_uri=%s&scope=%s&state=%s" % (appid, redirect_uri, scope, state)
})
receive_code.py:
from django.shortcuts import redirect
from django.core.cache import cache
import requests
from django.contrib.auth.models import User
from game.models.player.player import Player
from django.contrib.auth import login
from random import randint
def receive_code(request):
data = request.GET
code = data.get('code')
state = data.get('state')
if not cache.has_key(state):
return redirect("index")
cache.delete(state)
apply_access_token_url = "https://www.acwing.com/third_party/api/oauth2/access_token/"
params = {
'appid': "273",
'secret': "78d8a6dd97284e83b38bb36af115af6b",
'code': code
}
access_token_res = requests.get(apply_access_token_url, params=params).json()
access_token = access_token_res['access_token']
openid = access_token_res['openid']
players = Player.objects.filter(openid=openid)
if players.exists(): # 如果该用户已存在,则无需重新获取信息,直接登录即可
login(request, players[0].user)
return redirect("index")
get_userinfo_url = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"
params = {
"access_token": access_token,
"openid": openid
}
userinfo_res = requests.get(get_userinfo_url, params=params).json()
username = userinfo_res['username']
photo = userinfo_res['photo']
while User.objects.filter(username=username).exists(): # 找到一个新用户名
username += str(randint(0, 9))
user = User.objects.create(username=username)
player = Player.objects.create(user=user, photo=photo, openid=openid)
login(request, user)
return redirect("index")
更新urls:
进入acapp/game/urls/settings/acwing/index.py
index.py:
from django.urls import path
from game.views.settings.acwing.web.apply_code import apply_code
from game.views.settings.acwing.web.receive_code import receive_code
urlpatterns = [
path("web/apply_code/", apply_code, name="settings_acwing_web_apply_code"),
path("web/receive_code/", receive_code, name="settings_acwing_web_receive_code"),
]
总的settings的index:
acapp/game/urls/settings/index.py
from django.urls import path, include
from game.views.settings.getinfo import getinfo
from game.views.settings.login import signin
from game.views.settings.logout import signout
from game.views.settings.register import register
urlpatterns = [
path("getinfo/", getinfo, name="settings_getinfo"),
path("login/", signin, name="settings_login"),
path("logout/", signout, name="settings_logout"),
path("register/", register, name="settings_register"),
path("acwing/", include("game.urls.settings.acwing.index")),
]
修复之前getinfo.py中的bug:
acapp/game/views/settings/getinfo.py
from django.http import JsonResponse
from game.models.player.player import Player
def getinfo_acapp(request):
player = Player.objects.all()[0]
return JsonResponse({
'result': "success",
'username': player.user.username,
'photo': player.photo,
})
def getinfo_web(request):
user = request.user
if not user.is_authenticated:
return JsonResponse({
'result': "未登录"
})
else:
player = Player.objects.get(user=user)
return JsonResponse({
'result': "success",
'username': player.user.username,
'photo': player.photo,
})
def getinfo(request):
platform = request.GET.get('platform')
if platform == "ACAPP":
return getinfo_acapp(request)
elif platform == "WEB":
return getinfo_web(request)
更改acapp/game/static/js/src/settings/zbase.js
class Settings {
constructor(root) {
this.root = root;
this.platform = "WEB";
if (this.root.AcWingOS) this.platform = "ACAPP";
this.username = "";
this.photo = "";
this.$settings = $(`
登录
注册
AcWing一键登录
注册
登录
AcWing一键登录
`);
this.$login = this.$settings.find(".ac-game-settings-login");
this.$login_username = this.$login.find(".ac-game-settings-username input");
this.$login_password = this.$login.find(".ac-game-settings-password input");
this.$login_submit = this.$login.find(".ac-game-settings-submit button");
this.$login_error_message = this.$login.find(".ac-game-settings-error-message");
this.$login_register = this.$login.find(".ac-game-settings-option");
this.$login.hide();
this.$register = this.$settings.find(".ac-game-settings-register");
this.$register_username = this.$register.find(".ac-game-settings-username input");
this.$register_password = this.$register.find(".ac-game-settings-password-first input");
this.$register_password_confirm = this.$register.find(".ac-game-settings-password-second input");
this.$register_submit = this.$register.find(".ac-game-settings-submit button");
this.$register_error_message = this.$register.find(".ac-game-settings-error-message");
this.$register_login = this.$register.find(".ac-game-settings-option");
this.$register.hide();
//新增
this.$acwing_login = this.$settings.find('.ac-game-settings-acwing img');
this.root.$ac_game.append(this.$settings);
this.start();
}
start() {
this.getinfo();
this.add_listening_events();
}
add_listening_events() {
let outer = this;
this.add_listening_events_login();
this.add_listening_events_register();
this.$acwing_login.click(function() {
outer.acwing_login();
});
}
add_listening_events_login() {
let outer = this;
this.$login_register.click(function() {
outer.register();
});
this.$login_submit.click(function() {
outer.login_on_remote();
});
}
add_listening_events_register() {
let outer = this;
this.$register_login.click(function() {
outer.login();
});
this.$register_submit.click(function() {
outer.register_on_remote();
});
}
//新增
acwing_login() {
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/acwing/web/apply_code/",
type: "GET",
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
window.location.replace(resp.apply_code_url);
}
}
});
}
login_on_remote() { // 在远程服务器上登录
let outer = this;
let username = this.$login_username.val();
let password = this.$login_password.val();
this.$login_error_message.empty();
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/login/",
type: "GET",
data: {
username: username,
password: password,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload();
} else {
outer.$login_error_message.html(resp.result);
}
}
});
}
register_on_remote() { // 在远程服务器上注册
let outer = this;
let username = this.$register_username.val();
let password = this.$register_password.val();
let password_confirm = this.$register_password_confirm.val();
this.$register_error_message.empty();
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/register/",
type: "GET",
data: {
username: username,
password: password,
password_confirm: password_confirm,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload(); // 刷新页面
} else {
outer.$register_error_message.html(resp.result);
}
}
});
}
logout_on_remote() { // 在远程服务器上登出
if (this.platform === "ACAPP") return false;
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/logout/",
type: "GET",
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload();
}
}
});
}
register() { // 打开注册界面
this.$login.hide();
this.$register.show();
}
login() { // 打开登录界面
this.$register.hide();
this.$login.show();
}
getinfo() {
let outer = this;
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/getinfo/",
type: "GET",
data: {
platform: outer.platform,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
outer.username = resp.username;
outer.photo = resp.photo;
outer.hide();
outer.root.menu.show();
} else {
outer.login();
}
}
});
}
hide() {
this.$settings.hide();
}
show() {
this.$settings.show();
}
}
注意更改js一定是要在acapp/game/static,而不是在acapp/static里操作,否则打包程序打包无效。
进入acapp/game/views/settings/acwing/acapp
apply_code.py:
from django.http import JsonResponse
from urllib.parse import quote
from random import randint
from django.core.cache import cache
def get_state():
res = ""
for i in range(8):
res += str(randint(0, 9))
return res
def apply_code(request):
appid = "273"
redirect_uri = quote("https://app273.acapp.acwing.com.cn/settings/acwing/acapp/receive_code/")
scope = "userinfo"
state = get_state()
cache.set(state, True, 7200) # 有效期2小时
return JsonResponse({
'result': "success",
'appid': appid,
'redirect_uri': redirect_uri,
'scope': scope,
'state': state,
})
receive_code.py
from django.http import JsonResponse
from django.core.cache import cache
import requests
from django.contrib.auth.models import User
from game.models.player.player import Player
from random import randint
def receive_code(request):
data = request.GET
if "errcode" in data:
return JsonResponse({
'result': "apply failed",
'errcode': data['errcode'],
'errmsg': data['errmsg'],
})
code = data.get('code')
state = data.get('state')
if not cache.has_key(state):
return JsonResponse({
'result': "state not exist"
})
cache.delete(state)
apply_access_token_url = "https://www.acwing.com/third_party/api/oauth2/access_token/"
params = {
'appid': "273",
'secret': "19f22bef139b44079d1905d6a78f6ca9",
'code': code
}
access_token_res = requests.get(apply_access_token_url, params=params).json()
access_token = access_token_res['access_token']
openid = access_token_res['openid']
players = Player.objects.filter(openid=openid)
if players.exists(): # 如果该用户已存在,则无需重新获取信息,直接登录即可
player = players[0]
return JsonResponse({
'result': "success",
'username': player.user.username,
'photo': player.photo,
})
get_userinfo_url = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"
params = {
"access_token": access_token,
"openid": openid
}
userinfo_res = requests.get(get_userinfo_url, params=params).json()
username = userinfo_res['username']
photo = userinfo_res['photo']
while User.objects.filter(username=username).exists(): # 找到一个新用户名
username += str(randint(0, 9))
user = User.objects.create(username=username)
player = Player.objects.create(user=user, photo=photo, openid=openid)
return JsonResponse({
'result': "success",
'username': player.user.username,
'photo': player.photo,
})
更新urls:
进入acapp/game/urls/settings/acwing/index.py
index.py:
from django.urls import path
from game.views.settings.acwing.web.apply_code import apply_code as web_apply_code
from game.views.settings.acwing.web.receive_code import receive_code as web_receive_code
from game.views.settings.acwing.acapp.apply_code import apply_code as acapp_apply_code
from game.views.settings.acwing.acapp.receive_code import receive_code as acapp_receive_code
urlpatterns = [
path("web/apply_code/", web_apply_code, name="settings_acwing_web_apply_code"),
path("web/receive_code/", web_receive_code, name="settings_acwing_web_receive_code"),
path("acapp/apply_code/", acapp_apply_code, name="settings_acwing_acapp_apply_code"),
path("acapp/receive_code/", acapp_receive_code, name="settings_acwing_acapp_receive_code"),
]
更改acapp/game/static/js/src/settings/zbase.js
class Settings {
constructor(root) {
this.root = root;
this.platform = "WEB";
if (this.root.AcWingOS) this.platform = "ACAPP";
this.username = "";
this.photo = "";
this.$settings = $(`
登录
注册
AcWing一键登录
注册
登录
AcWing一键登录
`);
this.$login = this.$settings.find(".ac-game-settings-login");
this.$login_username = this.$login.find(".ac-game-settings-username input");
this.$login_password = this.$login.find(".ac-game-settings-password input");
this.$login_submit = this.$login.find(".ac-game-settings-submit button");
this.$login_error_message = this.$login.find(".ac-game-settings-error-message");
this.$login_register = this.$login.find(".ac-game-settings-option");
this.$login.hide();
this.$register = this.$settings.find(".ac-game-settings-register");
this.$register_username = this.$register.find(".ac-game-settings-username input");
this.$register_password = this.$register.find(".ac-game-settings-password-first input");
this.$register_password_confirm = this.$register.find(".ac-game-settings-password-second input");
this.$register_submit = this.$register.find(".ac-game-settings-submit button");
this.$register_error_message = this.$register.find(".ac-game-settings-error-message");
this.$register_login = this.$register.find(".ac-game-settings-option");
this.$register.hide();
this.$acwing_login = this.$settings.find('.ac-game-settings-acwing img');
this.root.$ac_game.append(this.$settings);
this.start();
}
start() {
if (this.platform === "ACAPP") {
this.getinfo_acapp();
} else {
this.getinfo_web();
this.add_listening_events();
}
}
add_listening_events() {
let outer = this;
this.add_listening_events_login();
this.add_listening_events_register();
this.$acwing_login.click(function() {
outer.acwing_login();
});
}
add_listening_events_login() {
let outer = this;
this.$login_register.click(function() {
outer.register();
});
this.$login_submit.click(function() {
outer.login_on_remote();
});
}
add_listening_events_register() {
let outer = this;
this.$register_login.click(function() {
outer.login();
});
this.$register_submit.click(function() {
outer.register_on_remote();
});
}
acwing_login() {
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/acwing/web/apply_code/",
type: "GET",
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
window.location.replace(resp.apply_code_url);
}
}
});
}
login_on_remote() { // 在远程服务器上登录
let outer = this;
let username = this.$login_username.val();
let password = this.$login_password.val();
this.$login_error_message.empty();
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/login/",
type: "GET",
data: {
username: username,
password: password,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload();
} else {
outer.$login_error_message.html(resp.result);
}
}
});
}
register_on_remote() { // 在远程服务器上注册
let outer = this;
let username = this.$register_username.val();
let password = this.$register_password.val();
let password_confirm = this.$register_password_confirm.val();
this.$register_error_message.empty();
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/register/",
type: "GET",
data: {
username: username,
password: password,
password_confirm: password_confirm,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload(); // 刷新页面
} else {
outer.$register_error_message.html(resp.result);
}
}
});
}
logout_on_remote() { // 在远程服务器上登出
if (this.platform === "ACAPP") return false;
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/logout/",
type: "GET",
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
location.reload();
}
}
});
}
register() { // 打开注册界面
this.$login.hide();
this.$register.show();
}
login() { // 打开登录界面
this.$register.hide();
this.$login.show();
}
acapp_login(appid, redirect_uri, scope, state) {
let outer = this;
this.root.AcWingOS.api.oauth2.authorize(appid, redirect_uri, scope, state, function(resp) {
console.log("called from acapp_login function");
console.log(resp);
if (resp.result === "success") {
outer.username = resp.username;
outer.photo = resp.photo;
outer.hide();
outer.root.menu.show();
}
});
}
getinfo_acapp() {
let outer = this;
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/acwing/acapp/apply_code/",
type: "GET",
success: function(resp) {
if (resp.result === "success") {
outer.acapp_login(resp.appid, resp.redirect_uri, resp.scope, resp.state);
}
}
});
}
getinfo_web() {
let outer = this;
$.ajax({
url: "https://app273.acapp.acwing.com.cn/settings/getinfo/",
type: "GET",
data: {
platform: outer.platform,
},
success: function(resp) {
console.log(resp);
if (resp.result === "success") {
outer.username = resp.username;
outer.photo = resp.photo;
outer.hide();
outer.root.menu.show();
} else {
outer.login();
}
}
});
}
hide() {
this.$settings.hide();
}
show() {
this.$settings.show();
}
}