在线代理服务器网站,什么网站可以自己做字,网页设计属于平面设计吗,免费影视剧网站笔记内容转载自 AcWing 的 Django 框架课讲义#xff0c;课程链接#xff1a;AcWing Django 框架课。
AcApp 端使用 AcWing 一键授权登录的流程与之前网页端的流程一样#xff0c;只有申请授权码这一步有一点细微的差别#xff1a; 我们在打开 AcApp 应用之后会自动向 AcW…笔记内容转载自 AcWing 的 Django 框架课讲义课程链接AcWing Django 框架课。
AcApp 端使用 AcWing 一键授权登录的流程与之前网页端的流程一样只有申请授权码这一步有一点细微的差别 我们在打开 AcApp 应用之后会自动向 AcWing 请求账号登录客户端会向后端服务器请求一些参数然后后端服务器向 AcWing 请求授权码然后 AcWing 在接到请求之后会询问用户是否要授权登录如果用户同意了那么 AcWing 会给客户端发送一个授权码客户端可以通过授权码加上自己的身份信息向 AcWing 服务器请求自己的授权令牌 access_token 和用户的 openid最后客户端在拿到令牌和 ID 后即可向 AcWing 服务器请求用户的用户名和头像等信息。
在网页端授权登录时我们使用的方法是通过 URL 的方式重定向到某一个链接里申请授权码而这次的 AcApp 不是通过链接而是通过 AcWing 的一个 API 申请请求授权码的 API
AcWingOS.api.oauth2.authorize(appid, redirect_uri, scope, state, callback);参数说明
appid应用的唯一 ID可以在 AcWing 编辑 AcApp 的界面里看到redirect_uri接收授权码的地址表示 AcWing 端要将授权码返回到哪个链接需要对链接进行编码Python3 中使用 urllib.parse.quoteJava 中使用 URLEncoder.encodescope申请授权的范围目前只需填 userinfostate用于判断请求和回调的一致性授权成功后原样返回该参数值即接收授权码的地址需要判断是否是 AcWing 发来的请求判断收到的 state 与发送出去的 state 是否相同如果不是直接 Pass。该参数可用于防止 CSRF 攻击跨站请求伪造攻击建议第三方带上该参数可设置为简单的随机数如果是将第三方授权登录绑定到现有账号上那么推荐用 随机数 user_id 作为 state 的值可以有效防止CSRF攻击。此处 state 可以存到 Redis 中设置两小时有效期callbackredirect_uri 返回后的回调函数即接受 receive_code 函数向前端返回的信息。
用户同意授权后会将 code 和 state 传递给 redirect_uri。
如果用户拒绝授权则将会收到如下错误码
{errcode: 40010errmsg: user reject
}我们在 game/views/settings/acwing/acapp 目录中将之前网页端的 apply_code.py 与 receive_code.py 复制过来然后对 apply_code.py 进行一点小修改这次不是返回一个链接而是返回四个参数
from django.http import JsonResponse
from django.core.cache import cache
from urllib.parse import quote
from random import randintdef get_state(): # 获得8位长度的随机数res for i in range(8):res str(randint(0, 9))return resdef apply_code(request):appid 4007redirect_uri quote(https://app4007.acapp.acwing.com.cn/settings/acwing/acapp/receive_code/)scope userinfostate get_state()cache.set(state, True, 7200) # 有效期2小时# 需要返回四个参数return JsonResponse({result: success,appid: appid,redirect_uri: redirect_uri,scope: scope,state: state,})进入 game/urls/settings/acwing 修改一下路由
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_codeurlpatterns [path(web/apply_code/, web_apply_code, namesettings_acwing_web_apply_code),path(web/receive_code/, web_receive_code, namesettings_acwing_web_receive_code),path(acapp/apply_code/, acapp_apply_code, namesettings_acwing_acapp_apply_code),path(acapp/receive_code/, acapp_receive_code, namesettings_acwing_acapp_receive_code),
]现在访问 https://app4007.acapp.acwing.com.cn/settings/acwing/acapp/apply_code/ 即可看到返回内容。
然后我们修改一下 receive_code.py
from django.http import JsonResponse
from django.core.cache import cache
from django.contrib.auth.models import User
from game.models.player.player import Player
from random import randint
import requestsdef receive_code(request):data request.GETif 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: 4007,secret: 0edf233ee876407ea3542220e2a8d83e,code: code}access_token_res requests.get(apply_access_token_url, paramsparams).json() # 申请授权令牌access_token access_token_res[access_token]openid access_token_res[openid]players Player.objects.filter(openidopenid) # filter不管存不存在都会返回一个列表get如果不存在会报异常if players.exists(): # 用户如果已存在就直接返回用户player players[0]return JsonResponse({result: success,username: player.user.username,avatar: player.avatar,})get_userinfo_url https://www.acwing.com/third_party/api/meta/identity/getinfo/params {access_token: access_token,openid: openid}get_userinfo_res requests.get(get_userinfo_url, paramsparams).json() # 申请获取用户信息username get_userinfo_res[username]avatar get_userinfo_res[photo]while User.objects.filter(usernameusername).exists(): # 如果当前用户的用户名已经存在则在其后面添加若干位随机数username str(randint(0, 9))user User.objects.create(usernameusername) # 创建该用户没有密码player Player.objects.create(useruser, avataravatar, openidopenid)return JsonResponse({result: success,username: player.user.username,avatar: player.avatar,})接着我们修改前端文件也就是 game/static/js/src/settings 目录中的 Settings 类
class Settings {constructor(root) {this.root root;this.platform WEB; // 默认为Web前端if (this.root.acwingos) this.platform ACAPP;this.username ; // 初始用户信息为空this.avatar ;this.$settings $(...);...this.start();}start() { // 在初始化时需要从服务器端获取用户信息if (this.platform WEB) {this.getinfo_web();this.add_listening_events();} else {this.getinfo_acapp();}}add_listening_events() { // 绑定监听函数...}add_listening_events_login() {...}add_listening_events_register() {...}login_on_remote() { // 在远程服务器上登录...}register_on_remote() { // 在远程服务器上注册...}acwing_login() {...}register() { // 打开注册界面...}login() { // 打开登录界面...}getinfo_web() { // 此处将之前的getinfo函数名进行了修改用来区分let outer this;$.ajax({url: https://app4007.acapp.acwing.com.cn/settings/getinfo/, // 用AcWing部署// url: http://8.130.54.44:8000/settings/getinfo/, // 用云服务器部署type: GET,data: {platform: outer.platform,},success: function(resp) { // 调用成功的回调函数返回的Json字典会传给respconsole.log(resp); // 控制台输出查看结果if (resp.result success) {outer.username resp.username;outer.avatar resp.avatar;outer.hide();outer.root.menu.show();} else { // 如果未登录则需要弹出登录界面outer.login();}}});}acapp_login(appid, redirect_uri, scope, state) {let outer this;// resp是redirect_uri的返回值此处为用户名和头像this.root.acwingos.api.oauth2.authorize(appid, redirect_uri, scope, state, function(resp) {console.log(resp);if (resp.result success) {outer.username resp.username;outer.avatar resp.avatar;outer.hide();outer.root.menu.show();}});}getinfo_acapp() {let outer this;$.ajax({url: https://app4007.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);}}});}hide() {this.$settings.hide();}show() {this.$settings.show();}
}注意如果遇到跨域问题Access to XMLHttpRequest at XXX大概率是某个文件的内容写错了可以检查 uWSGI 启动后的报错内容修改代码。