zoukankan      html  css  js  c++  java
  • Python 实现微信小程序的用户登录

         小程序可以通过官方提供的登录能力来获取用户身份的标示,具体文档可以参考 这里,通过流程时序可以看到,对于需要和前端配合的服务端开发,主要实现的就是通过小程序提供的 code 换取用户的 openid 和 session_key,并用换取到的 openid 和 secret_key 作为自定义的登录态。分析后得知,作为小程序后端的开发,主要实现以下几部分内容:

      - 提供一个 HTTP 接口,供小程序方使用,传递 code;

       - 换取用户身份标识;

       - 维护一个自定义的登录态;

           - 需要存储用户的 openid,以备后续使用。

    1. 提供给小程序一个 HTTP 接口,接口使用 Tornado 框架

         为了简化思路,下面代码都没有做各种异常处理!

    class LoginHandler(RequestHandler):
    
        def post(self):
            req_data = json.loads(self.request.body)
    
            js_code = req_data.get('js_code')
    
            # 这里是换取用户的信息
            user_info = get_user_info(js_code=js_code)
    
            openid = user_info['openid']
            session_key = user_info['session_key']
            user_uuid = str(uuid.uuid4())  # 暴露给小程序端的用户标示
            
            # 用来维护用户的登录态
            User.save_user_session(
                user_uuid=user_uuid,
                openid=openid,
                session_key=session_key
            )
            # 微信小程序不能设置cookie,把用户信息存在了 headers 中
            self.set_header('Authorization', user_uuid)
            
            # 存储用户信息
            User.save_user_info(open_id=openid)
    
            self.set_status(204)

    2. 换取用户身份标示,直接使用 Requests 请求微信的相关接口,获取数据

     1 def get_user_info(js_code):
     2 
     3     req_params = {
     4         "appid": 'app_id',  # 小程序的 ID
     5         "secret": 'secret',  # 小程序的 secret
     6         "js_code": js_code,
     7         "grant_type": 'authorization_code'
     8     }
     9     req_result = requests.get('https://api.weixin.qq.com/sns/jscode2session', 
    10                               params=req_params, timeout=3, verify=False)
    11     return req_result.json()

    3. 维护一个自定义的登录态,使用了 Redis

     1 user_redis = StrictRedis.from_url('redis//localhost:6379')
     2 
     3 
     4  class User(object):
     5 
     6     REDIS_EXPIRES = 7 * 24 * 60 * 60
     7 
     8     @classmethod
     9     def save_user_session(cls, user_uuid, openid, session_key):
    10         user_session_value = {
    11             'openid': openid,
    12             'session_key': session_key
    13         }
    14         user_session_key = 'US:' + user_uuid
    15         with user_redis.pipeline(transaction=False) as pipe:
    16             pipe.hmset(user_session_key, user_session_value)
    17             pipe.expire(user_session_key, cls.REDIS_EXPIRES)
    18             pipe.execute()

    4. 存储用户信息,以备后用,这里使用了 MySQL,ORM 使用的是 SQLAlchemy

     1 from sqlalchemy import create_engine
     2 from sqlalchemy.ext.declarative import declarative_base
     3 
     4 # mysql 相关设置
     5 engine = create_engine('mysql://root:@localhost/wechat')
     6 conn = engine.connect()
     7 
     8 Base = declarative_base()
     9 Base.metadata.reflect(engine)
    10 tables = Base.metadata.tables
    11 
    12 class User(object):
    13     table = tables['user']
    14     
    15     @classmethod
    16     def save_user_info(cls, open_id):
    17         #  存储用户信息
    18         sql = cls.table.insert().values(open_id=open_id)
    19         conn.execute(sql)

    SQL 语句

    CREATE TABLE `user` (
      `id` int(20) unsigned NOT NULL AUTO_INCREMENT,
      `open_id` varchar(32) NOT NULL COMMENT '用户 open_id',
      `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
      PRIMARY KEY (`id`),
      KEY `idx_oid` (`open_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    全部代码可以点击 这里 获取!

  • 相关阅读:
    C#中RDLC合并两个列的值
    C#中RDLC控制某列的显示隐藏
    VS中RDLC提示类型不一致
    C#中使用NPOI提示(找到的程序集清单定义与程序集引用不匹配)
    Web项目访问在C盘的图片(不在当前项目路径下的图片)
    【转】主成分分析(PCA)
    【转】协方差的意义
    [转]hpp.h与.h的区别
    SPEC-RFC3261总述
    (转载)VoLTE简介
  • 原文地址:https://www.cnblogs.com/qiaojushuang/p/9171680.html
Copyright © 2011-2022 走看看