当前位置: 首页 > news >正文

php 建设网站白杨seo

php 建设网站,白杨seo,免费的行情网站app网页,做淘宝客个人网站飞书开发学习笔记(六)-网页应用免登 一.上一例的问题修正 在上一例中,飞书登录查看网页的界面显示是有误的,看了代码,理论上登录成功之后,应该显示用户名等信息。 最后的res.nickName是用户名,res.i18nName.en_us是英…

飞书开发学习笔记(六)-网页应用免登

一.上一例的问题修正

在上一例中,飞书登录查看网页的界面显示是有误的,看了代码,理论上登录成功之后,应该显示用户名等信息。
最后的res.nickName是用户名,res.i18nName.en_us是英文名

function showUser(res) {// 展示用户信息// 头像$("#img_div").html(`<img src="${res.avatarUrl}" width="100%" height=""100%/>`);// 名称$("#hello_text_name").text(lang === "zh_CN" || lang === "zh-CN"? `${res.nickName}`: `${res.i18nName.en_us}`);// 欢迎语$("#hello_text_welcome").text(lang === "zh_CN" || lang === "zh-CN" ? "欢迎使用飞书" : "welcome to Feishu");
}

而这个页面结果显然是不正确的
在这里插入图片描述
仔细检查Console.log,原来是接收config参数时出现了错误,python使用了分步调试,发现问题出在

ticket = auth.get_ticket()

在这里插入图片描述
再进一步分析变量,发现是

APP_ID = os.getenv("APP_ID")
APP_SECRET = os.getenv("APP_SECRET")
FEISHU_HOST = os.getenv("FEISHU_HOST")

三个变量获取错误,最后锁定源头是.env中三个变量定义以后没有换行,应该是在查看后不小心修改了格式保存引起的,在改为标准格式,每个变量定义后换行,重新读入,成功获取用户名等信息,
这也是一个小插曲,对于学习来说却耽误了一个小时。
在这里插入图片描述
这才是登录成功的界面
在这里插入图片描述

二.应用免登

紧接着上一案例,就是应用免登的介绍
应用免登:应用免登

免登流程
网页应用免登为网页应用提供了获取当前登录用户的飞书身份的能力,网页应用免登流程如下:

步骤一:获取用户登录预授权码。
步骤二:使用预授权码获取user_access_token。
步骤三:获取用户信息并完成登录。
步骤四:刷新已过期的user_access_token。

实际应用分为四步,每个步骤与上一例基本相同。
不同点为第三步,配置网页应用访问地址时,需要同时填写
在这里插入图片描述
进入飞书开放平台: https://open.feishu.cn/app
完成重定向URL填写
在这里插入图片描述
从工作台打开应用后,同时获取用户基本信息
在这里插入图片描述
在这里插入图片描述

三.代码结构

3.1代码结构树

|── README.zh.md     ----- 说明文档
|── doc_images     ----- 说明文档的图片资源
|── public
|  |── svg     ----- 前端图形文件
|  |──index.css     ----- 前端展示样式
|  |── index.js     ----- 前端主要交互代码(免登流程函数、用户信息展示函数)
|── templates
|  |──err_info.html     ----- 前端错误信息展示页面
|  |── index.html     ----- 前端用户信息展示页面
|── auth.py     ----- 服务端免登流程类、错误信息处理类
|── server.py     ----- 服务端核心业务代码
|── requirements.txt     ----- 环境配置文件
└── .env     ----- 全局默认配置文件,主要存储 App ID 和 App Secret 等

3.2 index.html ----- 前端用户信息展示页面

在页面内部的js中,利用login_info判断是否已经登陆,如果已经登陆,就直接展示;否则走登陆程序
判断则转到index.js

<!DOCTYPE html>
<link rel="stylesheet" href="/public/index.css"/>
<html lang="en">
<head><meta charset="UTF-8"/><title>网页应用</title><script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head><!-- 在html文档中引入 JSSDK -->
<!-- JS 文件版本在升级功能时地址会变化,如有需要(比如使用新增的 API),请重新引用「网页应用开发指南」中的JSSDK链接,确保你当前使用的JSSDK版本是最新的。-->
<script type="text/javascript"
src="https://lf1-cdn-tos.bytegoofy.com/goofy/lark/op/h5-js-sdk-1.5.16.js">
</script><!-- 在页面上添加VConsole方便调试-->
<script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
<script>
// VConsole will be exported to `window.VConsole` by default.
var vConsole = new window.VConsole();
</script><body>
<div><div class="img"><!-- 头像 --><div id="img_div" class="img_div"> </div><span class="hello_text">Hello</span><!-- 名称 --><div id="hello_text_name" class="hello_text_name"></div><!-- 欢迎语 --><div id="hello_text_welcome" class="hello_text_welcome"></div></div><!-- 飞书icon --><div class="icon"><img src="../public/svg/icon.svg"/></div>
</div><!-- 在html文档中引入本demo免登流程函数apiAuth()和用户信息展示函数showUser(res) -->
<script src="/public/index.js"></script>
<!-- 根据服务端传来的参数login_info判断走免登流程还是直接展示用户信息 -->
<script>const login_info = '{{ login_info }}';console.log("login info: ", login_info);if (login_info == "alreadyLogin") {const user_info = JSON.parse('{{ user_info | tojson | safe }}');console.log("user: ", user_info.name);$('document').ready(showUser(user_info))} else {$('document').ready(apiAuth())}
</script></body>
</html>

3.3 index.js ----- 前端主要交互代码(免登流程函数、用户信息展示函数)

服务器端Route:server.py
1.服务器端执行get_appid获取app_id
2.调用JSAPI tt.requestAuthCode 获取 authorization code,参数为app_id,存储在 res.code
3.服务器端fetch把code传递给接入方服务端Route: callback,并获得user_info
4.成功后showUser(res)

let lang = window.navigator.language;
console.log(lang);function apiAuth() {if (!window.h5sdk) {console.log('invalid h5sdk')alert('please open in feishu')return}// 通过服务端的Route: get_appid获取app_id// 服务端Route: get_appid的具体内容请参阅服务端模块server.py的get_appid()函数// 为了安全,app_id不应对外泄露,尤其不应在前端明文书写,因此此处从服务端获取fetch(`/get_appid`).then(response1 => response1.json().then(res1 => {console.log("get appid succeed: ", res1.appid);// 通过error接口处理API验证失败后的回调window.h5sdk.error(err => {throw('h5sdk error:', JSON.stringify(err));});// 通过ready接口确认环境准备就绪后才能调用APIwindow.h5sdk.ready(() => {console.log("window.h5sdk.ready");console.log("url:", window.location.href);// 调用JSAPI tt.requestAuthCode 获取 authorization codett.requestAuthCode({appId: res1.appid,// 获取成功后的回调success(res) {console.log("getAuthCode succeed");//authorization code 存储在 res.code// 此处通过fetch把code传递给接入方服务端Route: callback,并获得user_info// 服务端Route: callback的具体内容请参阅服务端模块server.py的callback()函数fetch(`/callback?code=${res.code}`).then(response2 => response2.json().then(res2 => {console.log("getUserInfo succeed");// 示例Demo中单独定义的函数showUser,用于将用户信息展示在前端页面上showUser(res2);})).catch(function (e) {console.error(e)})},// 获取失败后的回调fail(err) {console.log(`getAuthCode failed, err:`, JSON.stringify(err));}})})})).catch(function (e) { // 从服务端获取app_id失败后的处理console.error(e)})
}function showUser(res) {// 展示用户信息// 头像$('#img_div').html(`<img src="${res.avatar_url}" width="100%" height=""100%/>`);// 名称$('#hello_text_name').text(lang === "zh_CN" || lang === "zh-CN" ? `${res.name}` : `${res.en_name}`);// 欢迎语$('#hello_text_welcome').text(lang === "zh_CN" || lang === "zh-CN" ? "欢迎使用飞书" : "welcome to Feishu");
}

3.4 auth.py ----- 服务端免登流程类、错误信息处理类

1.获取authorize_app_access_token,参数为 “app_id” 和 “app_secret”,获取到USER_ACCESS_TOKEN_URI
2.获取authorize_user_access_token,url 通过self._gen_url(USER_ACCESS_TOKEN_URI)获得
3.authorize_user_access_token的headers中 :“app_access_token” 位于HTTP请求的请求头
4.response.json().get(“data”)获得user_access_token


def authorize_app_access_token(self):# 获取 app_access_token, 依托于飞书开放能力实现. # 文档链接: https://open.feishu.cn/document/ukTMukTMukTM/ukDNz4SO0MjL5QzM/auth-v3/auth/app_access_token_internalurl = self._gen_url(APP_ACCESS_TOKEN_URI)# "app_id" 和 "app_secret" 位于HTTP请求的请求体req_body = {"app_id": self.app_id, "app_secret": self.app_secret}response = requests.post(url, req_body)Auth._check_error_response(response)self._app_access_token = response.json().get("app_access_token")# 这里也可以拿到user_info
# 但是考虑到服务端许多API需要user_access_token,如文档:https://open.feishu.cn/document/ukTMukTMukTM/uUDN04SN0QjL1QDN/document-docx/docx-overview
# 建议的最佳实践为先获取user_access_token,再获得user_info
# user_access_token后续刷新可以参阅文档:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/authen-v1/authen/refresh_access_token
def authorize_user_access_token(self, code):# 获取 user_access_token, 依托于飞书开放能力实现. # 文档链接: https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/authen-v1/authen/access_tokenself.authorize_app_access_token()url = self._gen_url(USER_ACCESS_TOKEN_URI)# “app_access_token” 位于HTTP请求的请求头headers = {"Content-Type": "application/json","Authorization": "Bearer " + self.app_access_token,}# 临时授权码 code 位于HTTP请求的请求体req_body = {"grant_type": "authorization_code", "code": code}response = requests.post(url=url, headers=headers, json=req_body)Auth._check_error_response(response)self._user_access_token = response.json().get("data").get("access_token")def get_user_info(self):# 获取 user info, 依托于飞书开放能力实现.  # 文档链接: https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/authen-v1/authen/user_infourl = self._gen_url(USER_INFO_URI)# “user_access_token” 位于HTTP请求的请求头headers = {"Authorization": "Bearer " + self.user_access_token,"Content-Type": "application/json",}response = requests.get(url=url, headers=headers)Auth._check_error_response(response)# 如需了解响应体字段说明与示例,请查询开放平台文档: # https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/authen-v1/authen/access_tokenreturn response.json().get("data")

3.5 server.py ----- 服务端核心业务代码

1.关键函数callback():
2.通过传递的code先获取 user_access_token
3. 再获取 user info
4. 将 user info 存入 session
5. get_home()查询USER_INFO_KEY 是否在session,在则免登,否则就登陆程序

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import loggingfrom auth import Auth
from dotenv import load_dotenv, find_dotenv
from flask import Flask, render_template, session, jsonify, request# 日志格式设置
LOG_FORMAT = "%(asctime)s - %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S"
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT)# const
# 在session中存储用户信息 user info 所需要的对应 session key
USER_INFO_KEY = "UserInfo"
# secret_key 是使用 flask session 所必须有的
SECRET_KEY = "ThisIsSecretKey"# 从 .env 文件加载环境变量参数
load_dotenv(find_dotenv())# 初始化 flask 网页应用
app = Flask(__name__, static_url_path="/public", static_folder="./public")
app.secret_key = SECRET_KEY
app.debug = True# 获取环境变量值
APP_ID = os.getenv("APP_ID")
APP_SECRET = os.getenv("APP_SECRET")
FEISHU_HOST = os.getenv("FEISHU_HOST")# 用获取的环境变量初始化免登流程类Auth
auth = Auth(FEISHU_HOST, APP_ID, APP_SECRET)# 业务逻辑类
class Biz(object):@staticmethoddef home_handler():# 主页加载流程return Biz._show_user_info()@staticmethoddef login_handler():# 需要走免登流程return render_template("index.html", user_info={"name": "unknown"}, login_info="needLogin")@staticmethoddef login_failed_handler(err_info):# 出错后的页面加载流程return Biz._show_err_info(err_info)# Session in Flask has a concept very similar to that of a cookie, # i.e. data containing identifier to recognize the computer on the network, # except the fact that session data is stored in a server.@staticmethoddef _show_user_info():# 直接展示session中存储的用户信息return render_template("index.html", user_info=session[USER_INFO_KEY], login_info="alreadyLogin")@staticmethoddef _show_err_info(err_info):# 将错误信息展示在页面上return render_template("err_info.html", err_info=err_info)# 出错时走错误页面加载流程Biz.login_failed_handler(err_info)
@app.errorhandler(Exception)
def auth_error_handler(ex):return Biz.login_failed_handler(ex)# 默认的主页路径
@app.route("/", methods=["GET"])
def get_home():# 打开本网页应用会执行的第一个函数# 如果session当中没有存储user info,则走免登业务流程Biz.login_handler()if USER_INFO_KEY not in session:logging.info("need to get user information")return Biz.login_handler()else:# 如果session中已经有user info,则直接走主页加载流程Biz.home_handler()logging.info("already have user information")return Biz.home_handler()@app.route("/callback", methods=["GET"])
def callback():# 获取 user info# 拿到前端传来的临时授权码 Codecode = request.args.get("code")# 先获取 user_access_tokenauth.authorize_user_access_token(code)# 再获取 user infouser_info = auth.get_user_info()# 将 user info 存入 sessionsession[USER_INFO_KEY] = user_inforeturn jsonify(user_info)@app.route("/get_appid", methods=["GET"])
def get_appid():# 获取 appid# 为了安全,app_id不应对外泄露,尤其不应在前端明文书写,因此此处从服务端传递过去return jsonify({"appid": APP_ID})if __name__ == "__main__":# 以debug模式运行本网页应用# debug模式能检测服务端模块的代码变化,如果有修改会自动重启服务app.run(host="0.0.0.0", port=3000, debug=True)

以上,免登流程完成。

http://www.zhongyajixie.com/news/1808.html

相关文章:

  • 无锡集团网站建设seo搜索优化邵阳
  • 中国矿井建设相关媒体网站网站seo优化免费
  • 锦州网站建设预订如何推广自己的店铺
  • 网页设计代码网站网站提交入口百度
  • 教师个人网站建设网络项目免费的资源网
  • 企业网站建设解决方案网站seo优化公司
  • wordpress 批量上传图片自己怎么优化网站排名
  • 28网站制作手机百度如何发布作品
  • 永久免费做网站 百度一下
  • 国外优秀网站案例搜索引擎营销的案例有哪些
  • 化妆品网站建设原因百度关键词优化软件怎么样
  • 顺义企业建站费用做seo推广一年大概的费用
  • 网站建设是学哪个学科在哪里做推广效果好
  • 网页建站的费用百度移动排名优化软件
  • 毕业设计代做网站web青岛网站seo公司
  • 棠下手机网站开发河北百度seo软件
  • ps网站logo制作教程长沙百度公司
  • 做网站培训班南京今日最新闻
  • 怎样做禁毒网站全球最受欢迎的网站排名
  • 寿光做网站免费培训机构管理系统
  • 汕尾做网站网页设计欣赏
  • 筹备网站建设网站seo优化培训
  • 做网站用什么字体字号企业网站开发
  • 互联网站建设株洲百度seo
  • 京东那个做快消的网站seo平台是什么意思
  • 新乡做网站的公司b2b推广网站
  • 做网站bbs是什么意思上海做网站优化
  • 专业做网站的团队seo快速收录快速排名
  • jsp借书网站开发百度官方网站首页
  • 男女做那个是的视频网站在哪里可以免费自学seo课程