标签:client 通过 定向 print debug webp from action 修改密码
oauth协议为用户资源的授权提供了一个安全的、开放而又建议的标准。oauth的授权不会是第三方初级到用户的账号信息(如用户名与密码),及第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此oauth是安全的。oauth是Open Authorization的简写
为了理解OAuth的适用场合,让我举一个假设的例子。
有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。
问题是只有得到用户的授权,Google才会同意"云冲印"读取这些照片。那么,"云冲印"怎样获得用户的授权呢?
传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。
(1)"云冲印"为了后续的服务,会保存用户的密码,这样很不安全。
(2)Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。
(3)"云冲印"拥有了获取用户储存在Google所有资料的权力,用户没法限制"云冲印"获得授权的范围和有效期。
(4)用户只有修改密码,才能收回赋予"云冲印"的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。
(5)只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。
OAuth就是为了解决上面这些问题而诞生的。
OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。
"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
客户端的授权模式:
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。
import base64
import random
import time
import json
import hmac
from datetime import datetime, timedelta
from flask import Flask, request, redirect, make_response
app = Flask(__name__)
users = {
‘lisir‘: [‘123456‘]
}
redirect_uri = ‘http://localhost:8888/client/passport‘
client_id = ‘666666‘
# 添加用户名到users字典中
users[client_id] = []
auth_code = {}
# 存放重定向uri
oauth_redirect_uri = []
#过期时间
timeout = 3600 * 2
#新版本token生成器
def get_token(data):
‘‘‘获取token‘‘‘
data = data.copy()
if "salt" not in data:
#随机生成的一个实数,在[0,1)范围内
data[‘salt‘] = random.random()
if "expires" not in data:
#设置过期时间
data[‘expires‘] = time.time() + timeout
payload = json.dumps(data).encode(‘utf8‘)
#生成签名
sig = _get_signature(payload)
return encode_token_bytes(payload+sig)
def get_code(uri, user_id):
‘‘‘授权码生成器‘‘‘
code = random.randint(0, 10000)
auth_code[code] = [uri, user_id]
return code
def verify_token(token):
‘‘‘token验证‘‘‘
decode_token = decode_token_bytes(token)
payload = decode_token[:-16]
sig = decode_token[-16:]
#生成签名
expected_sig = _get_signature(payload)
if sig != expected_sig:
print(‘token验证失败‘)
return {}
data = json.loads(payload.decode(‘utf8‘))
print(data)
if data.get(‘expires‘) >= time.time():
return data
return 0
#使用hmac为消息生成签名
def _get_signature(value):
a = hmac.new(b‘secret1234656‘, value).digest()
return a
#base64编码
def encode_token_bytes(data):
b = base64.urlsafe_b64encode(data)
print(b)
return b
def decode_token_bytes(data):
return base64.urlsafe_b64decode(data)
@app.route(‘/index‘, methods=[‘POST‘, ‘GET‘])
def index():
print(request.headers)
return "hello"
@app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])
def