最近发现自己公司的小程序被别人恶意的逆向并上线,官方不管,只能靠自己了。于是想到用以下方式,提升接口安全性,希望对大家有所帮助。
在微信小程序中,可以通过获取用户的 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 协议可以加密通信,并确保令牌在传输期间的安全性。