121 lines
4.8 KiB
Python
121 lines
4.8 KiB
Python
import hashlib
|
|||
|
|
import threading
|
||
|
|
from datetime import datetime, timedelta
|
||
|
|
from functools import wraps
|
||
|
|
from pathlib import Path
|
||
|
|
from zoneinfo import ZoneInfo
|
||
|
|
|
||
|
|
from Crypto.PublicKey import RSA
|
||
|
|
from django.conf import settings
|
||
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
||
|
|
from jwt import JWT, jwk_from_pem
|
||
|
|
from jwt.utils import get_int_from_datetime
|
||
|
|
from rest_framework.decorators import action
|
||
|
|
from rest_framework.request import Request
|
||
|
|
from rest_framework.response import Response
|
||
|
|
from rest_framework.viewsets import ViewSet
|
||
|
|
|
||
|
|
from wechat_token.token工具包 import sixToken
|
||
|
|
from wechat_数据库.雪花算法.雪花算法工具 import generator
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
def sync_lock_线程锁( lock ):
|
||
|
|
def decorator( fn ):
|
||
|
|
@wraps( fn )
|
||
|
|
def wrapper( *args, **kwargs ):
|
||
|
|
with lock:
|
||
|
|
return fn( *args, **kwargs )
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
return wrapper
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
return decorator
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
class 服务号网页授权接口ViewSets( ViewSet ):
|
||
|
|
lock = threading.Lock( )
|
||
|
|
|
||
|
|
def jwt_生成token( self, 有效时间_单位小时: int = 1 ):
|
||
|
|
# 读取私钥的 bytes字符串
|
||
|
|
private_key_pem_私钥 = Path( settings.BASE_DIR ).joinpath( "django_jwt_token/private.pem" ).read_bytes( )
|
||
|
|
|
||
|
|
# 创建一个 JWT对象
|
||
|
|
jwt对象实例 = JWT( ) # 创建对象
|
||
|
|
# 创建 payload
|
||
|
|
message = {
|
||
|
|
"oenid": "xiaozizi",
|
||
|
|
"uniond": "kladfj",
|
||
|
|
'iat': get_int_from_datetime( datetime.now( tz=ZoneInfo( key="utc" ) ) ), # 生成jwt-token的时间
|
||
|
|
'exp': get_int_from_datetime( datetime.now( tz=ZoneInfo( key="utc" ) ) + timedelta( hours=有效时间_单位小时 ) ), # 多长时间过期
|
||
|
|
}
|
||
|
|
# 获取私钥对象 (并且要私钥的密码)
|
||
|
|
私钥对象 = RSA.import_key( extern_key=private_key_pem_私钥, passphrase=settings.SECRET_KEY ).export_key( )
|
||
|
|
signing_key = jwk_from_pem( pem_content=私钥对象, )
|
||
|
|
token = jwt对象实例.encode( payload=message, key=signing_key, alg="RS256" )
|
||
|
|
return token
|
||
|
|
|
||
|
|
@action( detail=False, methods=[ "get", "post", "put", "delete" ], url_path="get_code" )
|
||
|
|
# @sync_lock_线程锁( lock=lock )
|
||
|
|
def 获取code接口( self, request: Request ):
|
||
|
|
pass
|
||
|
|
code = request.query_params.get( key="code", default=None )
|
||
|
|
print( "拿到的code的值是多少了呢?", code )
|
||
|
|
six_token = self.jwt_生成token( 有效时间_单位小时=24 )
|
||
|
|
uri = f"http://0.0.0.0:3000/home?six_token={six_token}"
|
||
|
|
# uri = f"https://wechat.sixgou.com?code={code}"
|
||
|
|
return HttpResponseRedirect( redirect_to=uri )
|
||
|
|
|
||
|
|
@action( detail=False, methods=[ "get", "post", "put", "delete" ], url_path="msg" )
|
||
|
|
# @sync_lock_线程锁( lock=lock )
|
||
|
|
def 响应微信服务器回调Token( self, request: Request ):
|
||
|
|
pass
|
||
|
|
print( request.headers )
|
||
|
|
signature = request.query_params.get( key="signature", default="" )
|
||
|
|
timestamp = request.query_params.get( key="timestamp", default="" )
|
||
|
|
nonce = request.query_params.get( key="nonce", default="" )
|
||
|
|
echostr = request.query_params.get( key="echostr", default="" )
|
||
|
|
print( signature, "===================" )
|
||
|
|
token = "xiaozizi"
|
||
|
|
params = [ token, timestamp, nonce ]
|
||
|
|
params.sort( )
|
||
|
|
tmp_str = "".join( params )
|
||
|
|
sig_str = f"{token}{timestamp}{nonce}"
|
||
|
|
res = hashlib.sha1( data=tmp_str.encode( encoding="utf-8" ) ).hexdigest( )
|
||
|
|
if sig_str == res:
|
||
|
|
print( "判断相等了" )
|
||
|
|
return HttpResponse( content=echostr )
|
||
|
|
|
||
|
|
@action( detail=False, methods=[ "get", "post", "put", "delete" ], url_path="signature" )
|
||
|
|
# @sync_lock_线程锁( lock=lock )
|
||
|
|
def signature( self, request: Request ):
|
||
|
|
"""
|
||
|
|
对网页请求使用 的功能进行授权 如:chooiseImage (在微信环境中,调用用户的相机的功能)
|
||
|
|
从前端的body,接收到url,然后后端生成随机字符串和时间戳
|
||
|
|
重点: 这个属性的key的字符,大小写要一模一样
|
||
|
|
:param request:
|
||
|
|
:return:
|
||
|
|
"""
|
||
|
|
pass
|
||
|
|
url = request.data.get( "url", None )
|
||
|
|
timestamp = get_int_from_datetime( value=datetime.now( ) )
|
||
|
|
nonceStr = generator.generate_str( )
|
||
|
|
jsapi_ticket = sixToken.get_wechat_tick_token( )
|
||
|
|
sig_str = f"jsapi_ticket={jsapi_ticket}&noncestr={nonceStr}×tamp={timestamp}&url={url}"
|
||
|
|
signature = hashlib.sha1( data=sig_str.encode( encoding="utf-8" ) ).hexdigest( )
|
||
|
|
return Response( data={ "nonceStr": nonceStr, "timestamp": timestamp, "signature": signature } )
|
||
|
|
|
||
|
|
# @action( detail=False, methods=[ "get",], url_path="认证接口文件" )
|
||
|
|
# @sync_lock_线程锁( lock=lock )
|
||
|
|
def 认证接口文件( self, request: Request ):
|
||
|
|
pass
|
||
|
|
return HttpResponse( content="kMmcLX8ZO79apUxA" )
|