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

这篇具有很好参考价值的文章主要介绍了Django学习笔记-AcApp端授权AcWing一键登录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。

AcApp 端使用 AcWing 一键授权登录的流程与之前网页端的流程一样,只有申请授权码这一步有一点细微的差别:

Django学习笔记-AcApp端授权AcWing一键登录,Django,django,学习,笔记,python,开发语言

我们在打开 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 randint

def get_state():  # 获得8位长度的随机数
    res = ''
    for i in range(8):
        res += str(randint(0, 9))
    return res

def 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_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'),
]

现在访问 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 requests

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': '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字典会传给resp
                console.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 启动后的报错内容修改代码。文章来源地址https://www.toymoban.com/news/detail-680511.html

到了这里,关于Django学习笔记-AcApp端授权AcWing一键登录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Django学习记录:初步认识django以及实现了简单的网页登录页面的前后端开发

    1、可以先删去template文件夹,并在setting里面删掉这一行 2、在pycharm中创建app: 3、启动app:编写URL与视图函数关系【urls.py】 ​ 编写视图函数【views.py】 ​ 启动pycharm项目 4、引用静态文件 其中有两个文件的导入:(jquery和bootstrap) jquery:https://code.jquery.com/jquery-3.6.0.min.js 可

    2024年02月14日
    浏览(37)
  • 【Django学习】(十五)API接口文档平台_项目流程分析_日志器_认证_授权

    使用API接口文档不经可以很好的的维护接口数据,还给测试人员的接口测试工作带来了便利; 我们可以在全局配置文件中添加路由路径生成接口文档 1.1在全局配置文件里指定用于支持coreapi的Schema 1.2在全局路由表中添加路径   页面效果: 2.1 一定要先在配置表中注册drf_yas

    2024年02月15日
    浏览(49)
  • Django学习笔记:第三章Django的路由

    URL是网站Web服务的入口。用户在浏览器输入URL发出请求后,django会根据路由系统,运行对应的视图函数,然后返回信息到浏览器中。 创建项目时,会自动生成urls.文件,文件中定义了项目的路由信息,成为项目的路由解析入口。在自建的应用中可以手动配置独立的urls.py文件。

    2024年02月16日
    浏览(54)
  • Django学习笔记:第二章django的安装和创建应用

    终端运行 查看django是否安装成功 在控制台运行 在特定文件夹内打开终端运行 生成 进入上图的Scripts文件夹内,打开终端 先正常安装VSCode 再安装python插件 安装Django插件,搜索django,安装前两个 特点 功能完善,开发速度快,安全性强 有完善的在线文档 模型自带数据库ORM组件

    2024年02月16日
    浏览(39)
  • django学习笔记(1)

    先创建一个文件夹用来放django的项目,我这里是My_Django_it 之后打开到该文件下,并用下面的指令来创建myDjango1项目 类似蓝图 模块化 在myDjango2中的settings.py中 最后一句加上\\\"app01.apps.App01Config\\\", 编写URL和视图的关系 bug: 若出现下面报错 说明端口被占用了,很可能是酷狗占用了,

    2024年02月15日
    浏览(34)
  • Django学习笔记

    创建项目:django-admin startproject 项目名 创建APP(进入工程目录):python manage.py startapp 网站名 创建库表(进入工程目录):python manage.py makemigrations 执行库表建立(进入工程目录):python manage.py migrate 启动运动:python manage.py runserver 模板渲染嵌入语法:在html可以嵌入后台语言 区分符

    2024年02月09日
    浏览(28)
  • Django+Celery学习笔记

    Django+Celery学习笔记 DJANGO中使用CELERY实现定时任务(用DJCELERY) https://www.cnblogs.com/wumingxiaoyao/p/8521567.html Django中celery机制的使用总结 https://blog.csdn.net/Enjolras_fuu/article/details/108513357 代码 https://github.com/furuiyang0715/celery_learn 参考 https://www.celerycn.io/yong-hu-zhi-nan/canvas-she-ji-gong-zuo-liu-che

    2024年02月12日
    浏览(30)
  • 【Django】学习笔记

    个人主页:丷从心· 系列专栏:Django MVC与MTV MVC设计模式 MTV设计模式 Django下载 Django工程创建与运行 创建工程 运行工程 子应用创建与注册安装 创建子应用 注册安装子应用 配置 settings.py 中的 INSTALLED_APPS 数据模型 ORM框架 配置 models.py 模型迁移 Tools - Run manage.py Task Admin站点 修

    2024年04月28日
    浏览(27)
  • Django学习笔记(2)

    属于自动执行了python manage.py 直接在里面运行startapp app01就可以创建app01的项目了 之后在setting.py中注册app01 其中用户中加入部门数据,如果是正常开始用ID,对于特别大的公司用字符串名称,这样可以防止连表的时间消耗,属于用空间换时间。 ###前端页面 上面的导航栏代码在

    2024年02月12日
    浏览(37)
  • Django学习笔记-实现聊天系统

    笔记内容转载自 AcWing 的 Django 框架课讲义,课程链接:AcWing Django 框架课。 聊天系统整体可以分为两部分:输入框与历史记录。 我们需要先修改一下之前代码中的一个小 BUG,当在一个窗口中按 Q 时,另一个窗口中点击鼠标左键也能攻击,因为按下按键的事件被所有窗口都捕

    2024年02月07日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包