day103:MoFang:用户登录部分:客户端提交登录信息&APICloud集成防水墙验证码&保存用户登录状态
目录
bug:修复jsonrpc修改源码以后celery无法运行的问题
bug:修复jsonrpc修改源码以后celery无法运行的问题
引入message和status直接写全路径

# 源码文件中, /flask_jwt_extended/view_decorators.py 94行左右
from jwt.exceptions import ExpiredSignatureError,InvalidTokenError
from flask_jwt_extended.exceptions import InvalidHeaderError
# 引入message和status直接写全路径
from application.utils.language.message import ErrorMessage as message # ***
from application.utils.language.status import APIStatus as status # *** def jwt_required(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
try:
verify_jwt_in_request()
except NoAuthorizationError:
return {"errno":status.CODE_NO_AUTHORIZATION,"errmsg":message.no_authorization}
except ExpiredSignatureError:
return {"errno":status.CODE_SIGNATURE_EXPIRED,"errmsg":message.authorization_has_expired}
except InvalidHeaderError:
return {"errno":status.CODE_INVALID_AUTHORIZATION,"errmsg":message.authorization_is_invalid}
except InvalidTokenError:
# ***
return {"errno": status.CODE_INVALID_AUTHORIZATION, "errmsg": message.authorization_is_invalid}
return fn(*args, **kwargs)
return wrapper # 146行左右
def fresh_jwt_required(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
try:
verify_fresh_jwt_in_request()
except NoAuthorizationError:
return {"errno":status.CODE_NO_AUTHORIZATION,"errmsg":message.no_authorization}
except ExpiredSignatureError:
return {"errno":status.CODE_SIGNATURE_EXPIRED,"errmsg":message.authorization_has_expired}
except InvalidHeaderError:
return {"errno": status.CODE_INVALID_AUTHORIZATION, "errmsg": message.authorization_is_invalid}
except InvalidTokenError:
return {"errno": status.CODE_INVALID_AUTHORIZATION, "errmsg": message.authorization_is_invalid}
return fn(*args, **kwargs)
return wrapper
修改 view_decorators.py 源码
1.客户端提交登录信息
用户在前端点击登录按钮:
前端执行LoginHandle方法:做了如下几件事:
1.验证用户名和密码是否填写
2.请求后端User.login接口,将用户名和密码发送给后端
html/login.html,代码:
<!-- 用户点击登录按钮 -->
<div class="form-item">
<img class="commit" @click="loginHandle" src="../static/images/commit.png">
</div> <script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
account: "",
password: "",
remember: false, // 是否记住登陆
music_play:true,
prev:{name:"",url:"",params:{}},
current:{name:"login",url:"login.html",params:{}},
}
},
methods:{
loginHandle(){
// 登陆处理
this.game.play_music('../static/mp3/btn1.mp3');
// 验证密码和账户是否填写
if(this.account.length<1 || this.password.length < 1){
api.alert({
title: '警告',
msg: '账户或密码不能为空!',
});
return;
}
// 发送登陆信息
this.axios.post('',{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.login",
"params": {
"account": this.account,
"password": this.password
}
}).then(response=>{
// 获取服务端数据
this.game.print(response.data);
}).catch(error=>{
if(error.response){
// 服务端返回错误
this.game.print(error.response.data.errmsg);
}else{
// 本地代码出现错误
this.game.print(error);
}
})
},
goto_register(){
this.game.goGroup("user",1);
},
}
})
}
</script>
</body>
</html>
2.在APICloud中集成防水墙验证码
使用微信扫码登录腾讯云控制台,然后根据官方文档,把验证码集成到项目中
验证码控制台: https://console.cloud.tencent.com/captcha
快速接入:https://007.qq.com/python-access.html?ADTAG=acces.start
新建验证应用,获取秘钥和应用ID[ 新用户可以领取一个免费的验证码套餐 ]


点击详情:

把验证码应用的ID和秘钥保存到application/settings/dev.py配置文件中.
# 防水墙验证码
CAPTCHA_GATEWAY="https://ssl.captcha.qq.com/ticket/verify"
CAPTCHA_APP_ID="2098385038"
CAPTCHA_APP_SECRET_KEY="05wGPzUzheZXvnuXPQfMaFg**"
1.前端配置防水墙相关信息
把防水墙的前端核心js文件在客户端根目录下index.html中使用script引入或者在src/main.js中通过import引入。
下载地址:https://ssl.captcha.qq.com/TCaptcha.js
在客户端项目的settings.js中添加配置app_id:
function init(){
var game = new Game("../mp3/bg1.mp3");
Vue.prototype.game = game;
axios.defaults.baseURL = "http://192.168.3.229:5000/api"
axios.defaults.timeout = 5000;
axios.defaults.withCredentials = false;
Vue.prototype.axios = axios;
Vue.prototype.uuid = UUID.generate;
Vue.prototype.settings = {
app_id: "2044977606" // 前端配置防水墙appid
}
}
2.客户端展示验证码
html/login.html,代码:
用户在前端点击登录按钮:
前端执行LoginHandle方法:做了如下几件事:
1.验证用户名和密码是否填写
2.前端向防水墙发送请求,防水墙会给前端返回一个结果res
3..当用户操作验证通过(res.ret=0)以后,请求后端User.login接口,将用户名和密码以及ticket(res.ticket)和randstr(res.randstr)发送给后端
<div class="form-item">
<img class="commit" @click="loginHandle" src="../static/images/commit.png">
</div> <script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
account: "",
password: "",
remember: false, // 是否记住登陆
music_play:true,
prev:{name:"",url:"",params:{}},
current:{name:"login",url:"login.html",params:{}},
}
},
methods:{
loginHandle(){
this.game.play_music('../static/mp3/btn1.mp3');
if(this.account.length<1 || this.password.length < 1){
api.alert({
title: '警告',
msg: '账户或密码不能为空!',
});
return;
} // ***图形验证码***
// 1.前端向防水墙发送请求,防水墙会给前端返回一个结果res
var captcha1 = new TencentCaptcha(this.settings.captcha_app_id,res=>{
// 2.当用户操作验证通过以后, 发送登陆信息和验证校验信息
if(res.ret == 0){
this.axios.post('',{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.login",
"params": {
"ticket": res.ticket, // 验证通过以后的防水墙验证码返回的临时凭证,需要发送给服务端,和腾讯服务器进行校验
"randstr": res.randstr, // 随机数, 为了让ticket更加随机和安全
"account": this.account,
"password": this.password
}
}).then(response=>{
// 获取服务端数据
this.game.print(response.data);
}).catch(error=>{
if(error.response){
// 服务端返回错误
this.game.print(error.response.data.errmsg);
}else{
// 本地代码出现错误
this.game.print(error);
}
});
}
});
captcha1.show(); // 显示验证码 },
goto_register(){
this.game.goGroup("user",1);
},
}
})
}
</script>
</body>
</html>
3.服务端校验验证码是否正确
User.login接口做了如下几件事:
1.后端校验防水墙验证码
2.根据前端发送的用户名和密码判断用户是否存在,若不存在返回错误信息
3.后端验证用户密码是否正确
4.如果1-2-3都通过,给用户生成access_token和refresh_token
5.将id,nickname,token返回给前端
from flask_jwt_extended import create_access_token,create_refresh_token,jwt_required,get_jwt_identity,jwt_refresh_token_required
from flask import jsonify,json
from sqlalchemy import or_
from .models import User
from message import ErrorMessage as message
from status import APIStatus as status
from flask import current_app,request
from urllib.parse import urlencode
from urllib.request import urlopen
@jsonrpc.method("User.login")
def login(ticket,randstr,account,password):
"""根据用户登录信息生成token"""
# 校验防水墙验证码
params = {
"aid": current_app.config.get("CAPTCHA_APP_ID"),
"AppSecretKey": current_app.config.get("CAPTCHA_APP_SECRET_KEY"),
"Ticket": ticket,
"Randstr": randstr,
"UserIP": request.remote_addr
} # 把字典数据转换成地址栏的查询字符串格式
# aid=xxx&AppSecretKey=xxx&xxxxx
params = urlencode(params)
url = current_app.config.get("CAPTCHA_GATEWAY") # 发送http的get请求
f = urlopen("%s?%s" % (url, params))
# https://ssl.captcha.qq.com/ticket/verify?aid=xxx&AppSecretKey=xxx&xxxxx content = f.read()
res = json.loads(content)
print(res) if int(res.get("response")) != 1:
# 验证失败
return {"errno": status.CODE_CAPTCHA_ERROR, "errmsg": message.captcaht_no_match} # 1. 根据账户信息和密码获取用户
if len(account) < 1:
return {"errno":status.CODE_NO_ACCOUNT,"errmsg":message.account_no_data}
user = User.query.filter(or_(
User.mobile==account,
User.email==account,
User.name==account
)).first() if user is None:
return {"errno": status.CODE_NO_USER,"errmsg":message.user_not_exists} # 验证密码
if not user.check_password(password):
return {"errno": status.CODE_PASSWORD_ERROR, "errmsg":message.password_error} # 2. 生成jwt token
access_token = create_access_token(identity=user.id)
refresh_token = create_refresh_token(identity=user.id) return {
"errno": status.CODE_OK,
"errmsg": message.ok,
"id": user.id,
"nickname": user.nickname if user.nickname else account,
"access_token": access_token,
"refresh_token":refresh_token
}
3.保存用户登录状态
1.APICloud提供的数据存储
基于APICloud提供的本地存储可以有效保存数据
// 保存数据到内存中
api.setGlobalData({
key: 'userName',
value: 'api'
});
// 从内存中获取数据
var userName = api.getGlobalData({
key: 'userName'
}); // 保存数据到文件中
api.setPrefs({//储存
key: 'userName',
value: 'api'
});
// 从文件中获取数据
api.getPrefs({//获取
key: 'userName'
}, function(ret, err) {
...
});
// 注意:基于api.getPrefs获取数组时,会出现转义格式的字符 // 从文件中删除数据
api.removePrefs({//删除
key: 'userName'
});
2.客户端保存用户登陆数据
static/js/main.js,代码:
class Game{
save(data){
// 保存数据到内存中
for(var key in data){
api.setGlobalData({
key: key,
value: data[key]
})
}
}
get(data){
// 从内存中获取数据
if(!Array.isArray(data)){
data = [data];
}
var result = {};
for(var key of data){
result[key] = api.getGlobalData({
"key": key
});
}
return result;
}
fsave(data){
// 保存数据到文件中
for(var key in data){
api.setPrefs({
"key": key,
value: data[key]
});
}
}
fremove(data){
// 从文件中删除数据
if(!Array.isArray(data)){
data = [data];
}
for(var key of data){
api.removePrefs({
"key": key,
});
}
}
fget(data){
// 从文件中获取数据
if(!Array.isArray(data)){
data = [data];
}
var value;
var result = {}
for(var key of data){
result[key] = api.getPrefs({
sync: true,
key: key
});
}
return result;
}
html/login.html,代码:
当后端用户登录校验通过后,要将id,nickname,token等数据保存在前端
1.如果用户登录的时候点击了记住密码,那就调用fsave永久保存
2.如果用户登录的时候没有点击记住密码,那就调用save暂时保存
methods:{
loginHandle(){
this.game.play_music('../static/mp3/btn1.mp3');
if(this.account.length<1 || this.password.length < 1){
api.alert({
title: '警告',
msg: '账户或密码不能为空!',
});
return;
}
var captcha1 = new TencentCaptcha(this.settings.captcha_app_id,res=>{
if(res.ret == 0){
this.axios.post('',{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.login",
"params": {
"ticket": res.ticket,
"randstr": res.randstr,
"account": this.account,
"password": this.password
}
}).then(response=>{
if(response.data.result.errno == 1000){
if( this.remember ){
// ***记住登陆***
this.game.fsave({
"id": response.data.result.id,
"nickname": response.data.result.nickname,
"access_token":response.data.result.access_token,
"refresh_token":response.data.result.refresh_token,
});
}else{
// ***不记住登陆***
this.game.save({
"id": response.data.result.id,
"nickname": response.data.result.nickname,
"access_token":response.data.result.access_token,
"refresh_token":response.data.result.refresh_token,
});
}
}
}).catch(error=>{
if(error.response){
this.game.print(error.response.data);
}else{
this.game.print(error);
}
});
}
});
captcha1.show();
},
goto_register(){
this.game.goGroup("user",1);
},
}
})
}
day103:MoFang:用户登录部分:客户端提交登录信息&APICloud集成防水墙验证码&保存用户登录状态的更多相关文章
- win10 uwp 保存用户选择文件夹
如果我们每次把临时处理的文件保存,都要让用户选择一次,用户会不会觉得uwp垃圾?如果我们每次打开应用,都从某个文件读取,而这个文件不在应用目录和已知的目录,那么每次都需要用户选择,用户会不会觉得uwp ...
- C#网页自动登录和提交POST信息的多种方法(转)
网页自动登录和提交POST信息的核心就是分析网页的源代码(HTML),在C#中,可以用来提取网页HTML的组件比较多,常用的用WebBrowser.WebClient.HttpWebRequest这三 ...
- 单点登录CAS使用记(三):实现自定义验证用户登录
问题: CAS自带的用户验证逻辑太过简单,如何像正常网站一样,通过验证DB中的用户数据,来验证用户以及密码的合法性呢? 方案1:CAS默认的JDBC扩展方案: CAS自带了两种简单的通过JDBC方式验 ...
- php使用session来保存用户登录信息
php使用session来保存用户登录信息 使用session保存页面登录信息 1.数据库连接配置页面:connectvars.php <?php //数据库的位置 define('DB_HOS ...
- C#三种模拟自动登录和提交POST信息的实现方法【转】
网页自动登录(提交Post内容)的用途很多,如验证身份.程序升级.网络投票等,以下是用C#实现的方法. 网页自动登录和提交POST信息的核心就是分析网页的源代码(HTML),在C#中,可以 ...
- 如何利用cookie来保存用户登录账号
众所周知,cookie在网页编写中不接或缺,今天就谈谈如何利用cookie技术来保存用户登录账号 1.首先是否保存用户登录账号当然是用户自行决定,所以我们需要在用户登录界面设置一个复选框,以此取得用户 ...
- C#三种模拟自动登录和提交POST信息的实现方法
网页自动登录(提交Post内容)的用途很多,如验证身份.程序升级.网络投票等,以下是用C#实现的方法. 网页自动登录和提交POST信息的核心就是分析网页的源代码(HTML),在C#中,可以 ...
- java—不同的用户登录以后可以看到不同的菜单(后台可以实现对用户菜单的管理) 1 (55)
实现不同的用户登录以后可以看到不同的菜单.(后台可以实现对用户菜单的管理.) 第一步:分析数据结构 1:用户表 表名:users 列名 类型 说明 id Varchar(32) 主键 n ...
- 云服务器 ECS Linux 保存用户登录操作命令记录
转载自 : https://help.aliyun.com/knowledge_detail/41210.html 云服务器 ECS Linux 如果要保存用户登录操作记录,则可以通过在 /etc/p ...
- django--之登录表单提交
前端代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
随机推荐
- Python3网络爬虫--爬取有声小说(附源码)
目录 一.目标 1.首页 2.网页源代码 二.爬取详情页 1.查看详情页 2.小说详情 3.小说简介 4.播放列表 三.爬取小说音频 1.确定数据加载方式 2.寻找真实音频播放地址 3.URL解码 4 ...
- goland 快捷键
goland常用快捷键 Coldestmonth 2018-07-17 17:26:37 18067 收藏 14版权Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/-/ )Ctrl+D ...
- 十大经典排序之希尔排序(C++实现)
希尔排序 思路: 1.选择一个增量序列 t1,t2,--,tk,其中 ti > tj, tk = 1(最后必须是1) 2.按增量序列个数 k,对序列进行 k 趟排序 代码实现: #include ...
- 大胖子走迷宫【spfa跑状态】【到这个点,并且这个胖 = max(到这个点,按照时间变的这个胖)
大胖子走迷宫 题意 思路 普通的bfs走迷宫,多加了一个熟悉,就是胖的圈数.可以来回走,普通的bfs可能不太好处理,我们把这些状态放进spfa跑. 状态定义为{x,y,fat}:坐标位置,胖的圈数. ...
- Ubuntu系统Root用户无法登录解决办法
默认 系统 root 登录 图形界面,出现 登录失败.解决方法如下: 1,登录普通用户, 打开终端执行命令, 使用su root或sudo -i切换到root用户(必须) su root 按照提示输入 ...
- 5.3dmax轴相关
# 知识点: 转换为可编辑的样条线(spline) chamfer 切角 Fillet 圆角 车削命令 书柜案例2 样条线(从图形到多边形) 1.在平面视图中选择矩形并创建一个矩形,将矩形转化为可编辑 ...
- 大数据组件对应Ranger插件的选择
在都是开源组件的前提下,一般需要我们多关注到组件和插件的版本和类型选择. 参考 https://zhuanlan.zhihu.com/p/370263573 https://www.bookstack ...
- Go_day08
Go的Io流 获取文件信息 //获取文件 fileinfo, err := os.Stat("./aa.txt")//相对绝对路径都可以 if err != nil { fmt.P ...
- 远程链接linux编程shell脚本
WinSCP-5.15.3-Setup.exe https://pan.baidu.com/s/1zr7ipq8i5rqm8tYS8GeKsQ
- Git添加SSH密钥步骤
1.先去本机上面看看用户主目录里面有没有.ssh这个文件夹 如果有的话,再看看该目录下有没有id_rsa和id_rsa_pub这两个文件: 若还是有,就直接跳过这一步到下一步:若是没有,我们需要创建S ...