Django学习笔记-AcApp端授权AcWing一键登录

笔记内容转载自 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.quote;Java 中使用 URLEncoder.encode
  • scope:申请授权的范围,目前只需填 userinfo
  • state:用于判断请求和回调的一致性,授权成功后原样返回该参数值,即接收授权码的地址需要判断是否是 AcWing 发来的请求(判断收到的 state 与发送出去的 state 是否相同),如果不是直接 Pass。该参数可用于防止 CSRF 攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数(如果是将第三方授权登录绑定到现有账号上,那么推荐用 随机数 + user_id 作为 state 的值,可以有效防止CSRF攻击)。此处 state 可以存到 Redis 中,设置两小时有效期;
  • callbackredirect_uri 返回后的回调函数,即接受 receive_code 函数向前端返回的信息。

用户同意授权后,会将 codestate 传递给 redirect_uri

如果用户拒绝授权,则将会收到如下错误码:

{errcode: "40010"errmsg: "user reject"
}

我们在 game/views/settings/acwing/acapp 目录中将之前网页端的 apply_code.pyreceive_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 = '4007'redirect_uri = quote('https://app4007.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,})

进入 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, 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'),
]

现在访问 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, params=params).json()  # 申请授权令牌access_token = access_token_res['access_token']openid = access_token_res['openid']players = Player.objects.filter(openid=openid)  # 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, params=params).json()  # 申请获取用户信息username = get_userinfo_res['username']avatar = get_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, avatar=avatar, openid=openid)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 启动后的报错内容修改代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/107081.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

05.sqlite3学习——DML(数据管理:插入、更新、删除)

目录 DML(数据管理:插入、更新、删除) 插入 更新 删除整个表 语法 实例 DML(数据管理:插入、更新、删除) 数据操纵(DML):用于增、删、改数据 作用:负…

Java设计模式-职责链模式

1 概述 在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如,公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的天数不同…

Mac OS 13.4.1 搜狗输入法导致的卡顿问题

一、Mac OS 系统版本 搜狗输入法已经更新到最新 二、解决方案 解决方案一 在我的电脑上面需要关闭 VSCode 和 Chrmoe 以后,搜狗输入法回复正常。 解决方案二 强制重启一下搜狗输入法。 可以用 unix 定时任务去隔 2个小时自动 kill 掉一次进程 # kill 掉 mac …

【SpringBoot】第一篇:redis使用

背景&#xff1a; 本文是教初学者如何正确使用和接入redis。 一、引入依赖 <!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><depen…

MyBatis快速入门以及环境搭建和CRUD的实现

目录 前言 一、MyBatis简介 1.MyBatis是什么 2.MyBatis的特点 3.mybatis的作用 4.MyBatis的应用场景 5.MyBatis优缺点 二、相关概念 1.ORM概述 2.常见的ORM框架 3.什么是持久层框架 三、MyBatis的工作原理 1.框架交互 2.工作原理 ​编辑 四、MyBatis环境搭建 1…

多次跑网络流(用于构造类)+霍尔定理证明可行:AGC317G

https://atcoder.jp/contests/abc317/tasks/abc317_g 一个很显然的思路&#xff0c;就是行向颜色连边&#xff0c;但约束条件展现出多个维度&#xff0c;所以可以考虑跑多次网络流。 但跑同样的网络流没有意义&#xff0c;所以每次跑完都要在残余网络上操作一下才可行。此题中…

JVM理论知识

一、JVM内存结构 java的内存模型主要分为5个部分&#xff0c;分别是&#xff1a;JVM堆、JVM栈、本地栈、方法区还有程序计数器&#xff0c;他们的用途分别是&#xff1a; JVM堆&#xff1a;新建的对象都会放在这里&#xff0c;他是JVM中所占内存最大的区域。他又分为新生区还…

项目---日志系统

目录 项目系统开发环境核心技术日志系统介绍为什么需要日志系统? 日志系统框架设计日志系统模块划分代码实现通用工具实现日志等级模块实现日志消息模块实现格式化模块实现落地模块实现日志器模块同步日志器异步日志器缓冲区实现异步工作器实现 回归异步日志器模块建造者模式日…

【JavaEE】Spring事务-事务的基本介绍-事务的实现-@Transactional基本介绍和使用

【JavaEE】Spring事务&#xff08;1&#xff09; 文章目录 【JavaEE】Spring事务&#xff08;2&#xff09;1. 为什么要使用事务2. Spring中事务的实现2.1 事务针对哪些操作2.2 MySQL 事务使用2.3 Spring 编程式事务&#xff08;手动挡&#xff09;2.4 Spring 声明式事务&#…

分享一种针对uni-app相对通用的抓包方案

PART1&#xff0c;前言 近年来混合开发APP逐渐成为主流的开发模式&#xff0c;与传统的开发模式相比混合开发极大的提升了开发效率&#xff0c;同时跨平台的特性也降低了开发成本&#xff0c;一直以来混合开发被诟病的性能问题随着技术的发展也得到改善。技术的发展往往是一把…

基于FPGA的Lorenz混沌系统verilog开发,含testbench和matlab辅助测试程序

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 将vivado的仿真结果导入到matlab显示三维混沌效果&#xff1a; 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 testbench如下所…

4.15 TCP Keepalive 和 HTTP Keep-Alive 是一个东西吗?

目录 HTTP 的 Keep-Alive TCP 的 Keepalive 总结&#xff1a; HTTP的Keep-Alive&#xff0c;是应用层&#xff08;用户态&#xff09;实现的&#xff0c;称为HTTP长连接&#xff1b; TCP的Keepalive&#xff0c;是由TCP层&#xff08;内核态&#xff09;实现的&#xff0c;…

下载的文件被Windows 11 安全中心自动删除

今天从CSDN上下载了自己曾经上传的文件&#xff0c;但是浏览器下载完之后文件被Windows安全中心自动删除&#xff0c;说是带病毒。实际是没有病毒的&#xff0c;再说了即便有病毒也不应该直接删除啊&#xff0c;至少给用户一个保留或删除的选项。 研究了一番&#xff0c;可以暂…

2023-8-25 最大异或对

题目链接&#xff1a;最大异或对 #include <iostream> #include <algorithm>using namespace std;const int N 100010, M 31 * N;int a[N]; int son[M][2], idx;void insert(int x) {int p 0;for(int i 30; i > 0; i --){int u x >> i & 1;if(…

求生之路2私人服务器开服搭建教程centos

求生之路2私人服务器开服搭建教程centos 大家好我是艾西&#xff0c;朋友想玩求生之路2(left4dead2)重回经典。Steam玩起来有时候没有那么得劲&#xff0c;于是问我有没有可能自己搭建一个玩玩。今天跟大家分享的就是求生之路2的自己用服务器搭建的一个心路历程。 &#xff0…

如何把本地项目上传github

一、在gitHub上创建新项目 【1】点击添加&#xff08;&#xff09;-->New repository 【2】填写新项目的配置项 Repository name&#xff1a;项目名称 Description &#xff1a;项目的描述 Choose a license&#xff1a;license 【3】点击确定&#xff0c;项目已在githu…

课程项目设计--spring security--认证管理功能--宿舍管理系统--springboot后端

写在前面&#xff1a; 还要实习&#xff0c;每次时间好少呀&#xff0c;进度会比较慢一点 本文主要实现是用户管理相关功能。 前文项目建立 文章目录 验证码功能验证码配置验证码生成工具类添加依赖功能测试编写controller接口启动项目 security配置拦截器配置验证码拦截器 …

threejs贴图系列(一)canvas贴图

threejs不仅支持各种texture的导入生成贴图&#xff0c;还可以利用canvas绘制图片作为贴图。这就用到了CanvasTexture&#xff0c;它接受一个canas对象。只要我们绘制好canvas&#xff0c;就可以作为贴图了。这里我们利用一张图片来实现这个效果。 基础代码&#xff1a; impo…

【C++初阶】模拟实现list

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

自组织映射

无监督深度学习&#xff1a; 无监督模型使神经网络能够执行聚类、异常检测、特征选择、特征提取、降维和推荐系统等任务。这些神经网络包括 自组织图、玻尔兹曼机、自动编码器。 什么是 SOM&#xff1f; 简而言之&#xff0c;自组织映射是一种基于竞争学习的人工神经网络&am…