Python3 - 微信小程序接口安全

最近发现自己公司的小程序被别人恶意的逆向并上线,官方不管,只能靠自己了。于是想到用以下方式,提升接口安全性,希望对大家有所帮助。

在微信小程序中,可以通过获取用户的 OpenID 和 Session Key 来保证服务器 API 的安全性:

1.授权token认证

from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route('/login', methods=['POST'])
def login():
    code = request.json.get('code')  # 获取登录凭证 code,微信登录客户端可以获取
    if not code:
        return jsonify({
    
    'error': 'Missing login credential'}), 400
    
    # 发送请求获取 session_key 和 openid
    appid = '示例' # 填写自己的
    msecret = '示例' # 填写自己的
    response = requests.get(f'https://api.weixin.qq.com/sns/jscode2session?appid={
      
      appid}&secret={
      
      msecret}&js_code={
      
      code}&grant_type=authorization_code')
    if response.status_code != 200:
        return jsonify({
    
    'error': f'Request failed with status {
      
      response.status_code}'}), 500
    
    result = response.json()
    openid = result.get('openid')
    session_key = result.get('session_key')
    if not openid or not session_key:
        return jsonify({
    
    'error': 'Failed to get openid and session_key'}), 500
    
    # 这里可以将 session_key 和 openid 存储到数据库或缓存中,以供后续使用

    return jsonify({
    
    'openid': openid, 'session_key': session_key}), 200

@app.route('/protected', methods=['GET'])
def protected():
    openid = request.headers.get('X-USER-OPENID')  # 获取请求头中的 openid
    session_key = get_session_by_openid(openid)  # 通过 openid 获取对应的 session_key

    # 在这里进行身份验证和访问控制,比如检查用户是否有访问该接口的权限
    # 如果身份验证和访问控制通过,则返回请求的数据

    return jsonify({
    
    'message': 'Hello, world!'}), 200

if __name__ == '__main__':
    app.run(debug=True)

在这个例子中,/login 路由用于获取 session_key 和 openid,并将其存储到数据库或缓存中。在 /protected 路由中,可以通过请求头中的 openid 获取对应的 session_key,并进行身份验证和访问控制。

需要注意的是,为了确保安全性,您应该使用 HTTPS 协议来加密通信,并在服务器上定期更换密钥。另外,为了防止恶意攻击者尝试使用假造的 openid 进行攻击,您应该在服务器端对 openid 进行校验,并确保只有经过授权的用户才能访问 API。

2.补充一下身份校验环节

from flask import Flask, request, jsonify
import requests
import jwt

app = Flask(__name__)

# 用于存储有效 session_key 的数据结构,可以替换为数据库等持久化存储
valid_session_keys = {
    
    }

@app.route('/login', methods=['POST'])
def login():
    code = request.json.get('code')  # 获取登录凭证 code
    if not code:
        return jsonify({
    
    'error': 'Missing login credential'}), 400
    
    # 发送请求获取 session_key 和 openid
    appid = '示例' # 填写自己的
    msecret = '示例' # 填写自己的
    response = requests.get(f'https://api.weixin.qq.com/sns/jscode2session?appid={
      
      appid}&secret={
      
      msecret}&js_code={
      
      code}&grant_type=authorization_code')
    if response.status_code != 200:
        return jsonify({
    
    'error': f'Request failed with status {
      
      response.status_code}'}), 500
    
    result = response.json()
    openid = result.get('openid')
    session_key = result.get('session_key')
    if not openid or not session_key:
        return jsonify({
    
    'error': 'Failed to get openid and session_key'}), 500
    
    # 将 session_key 存储到数据结构中,并生成 JWT 令牌返回给客户端
    valid_session_keys[session_key] = openid
    token = jwt.encode({
    
    'openid': openid}, 'your_secret_key', algorithm='HS256')

    return jsonify({
    
    'token': token}), 200

@app.route('/protected', methods=['GET'])
def protected():
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return jsonify({
    
    'error': 'Missing or invalid authorization header'}), 401
    
    token = auth_header[7:]
    try:
        payload = jwt.decode(token, 'your_secret_key', algorithms=['HS256'])
    except jwt.InvalidTokenError:
        return jsonify({
    
    'error': 'Invalid token'}), 401
    
    openid = payload.get('openid')
    if not openid or openid not in valid_session_keys:
        return jsonify({
    
    'error': 'Invalid token or user not authorized'}), 401

    # 在这里进行身份验证和访问控制,比如检查用户是否有访问该接口的权限
    # 如果身份验证和访问控制通过,则返回请求的数据
    
    return jsonify({
    
    'message': 'Hello, world!'}), 200

if __name__ == '__main__':
    app.run(debug=True)

在这个例子中,/login 路由用于获取 session_key,并将其存储到有效 session_key 的数据结构中。同时,生成一个 JWT 令牌,并将其作为响应返回给客户端。

/protected 路由中,首先检查请求头中的 Authorization 字段,并从中提取 JWT 令牌。然后,使用密钥对 JWT 令牌进行解密,并根据其中包含的 openid 进行身份验证和访问控制。

需要注意的是,使用 JWT 令牌进行身份验证可以确保 API 请求是由经过验证的用户发出的,并且可以避免将 session_key 直接传递给客户端。另外,使用 HTTPS 协议可以加密通信,并确保令牌在传输期间的安全性。

猜你喜欢

转载自blog.csdn.net/qq_31810357/article/details/129802875