JWT的跨域身份验证简单案例 odoo 如何写JWT模块 让第三方系统进行免登录

JWT Python

下面是简单的 生成 JWT Web Token 和 验证Token

import jwt
from jwt import exceptions
import time

SECRET_KEY = "!kLbMLtW4@lFnBlt"


# 创建JWT-Token
def create_token(name):
    global SECRET_KEY
    headers = {
     
        "alg": "HS256",
        "typ": "JWT"
    }
    exp = int(time.time() + 20)
    print(exp)
    payload = {
     
        "iat": exp,
        "login": name,
    }
    token = jwt.encode(payload=payload, key=SECRET_KEY, algorithm='HS256', headers=headers).decode('utf-8')

    return token


## 验证JWT-Token
def validate_token(token):
    global SECRET_KEY
    payload = None
    msg = None
    try:
        payload = jwt.decode(token, SECRET_KEY, True, algorithm='HS256')
    except exceptions.ExpiredSignatureError:
        msg = 'token expired'
    except jwt.DecodeError:
        msg = 'token fail'
    except jwt.InvalidTokenError:
        msg = 'invalidate token'
    return (payload, msg)


if __name__ == '__main__':
    token = create_token('admin')
    validate_token(token)

当我们学会了如何制作token 和验证token 那么一切就简单了

1、第三系统生成token 且payload 带有身份信息以及时间戳
请求被登录的系统

2、被登录的系统提供入口 验证token的有效性以及时间范围有效性
然后就是本系统登录的事情了

以下是采用Odoo开源框架作为案例

Odoo JWT 核心代码

   @http.route('/jwt/web/login', type='http', auth="none", csrf=False)
    def jwt_login(self, **kw):
        params = request.env['ir.config_parameter'].sudo()
        jwt_token = kw.get('token')
        redirect_url = kw.get('redirect_url', '/web')
        if redirect_url != '/web':
            redirect_url = base64.b64decode(redirect_url)

        if not jwt_token:
            _logger.error('缺少必要参数token')
            return '缺少必要参数token'

        # 获取 jwt token secret
        jwt_secret = params.get_param('oauth_jwt_secret', '')
        if not jwt_secret:
            _logger.error('验证密钥未配置,请联系管理员')
            return '验证密钥未配置,请联系管理员'

        try:
            data = jwt.decode(jwt_token, jwt_secret, algorithms='HS256')
        except jwt.ExpiredSignatureError as e:
            _logger.error(e)
            return '身份认证已过期/%s' % e
        except jwt.InvalidSignatureError as e:
            _logger.error(e)
            return '非法签名/%s' % e
        except Exception as e:
            _logger.info(e)
            return '请求失败,请联系系统管理员'

        # 验证 iat
        errmsg = self._validate_iat(data)
        if errmsg is not True:
            return errmsg

        login = data.get('login')
        if login:
            db = request.session.db
            registry = registry_get(db)
            with registry.cursor() as cr:
                env = api.Environment(cr, SUPERUSER_ID, {
     })
                user_id = env['res.users'].sudo().search([('login', '=', login)], limit=1)
                if user_id:
                    # 采用jwt_token作为临时密码进行登录验证
                    user_id.oauth_access_token = jwt_token
                    env.cr.commit()
                    uid = request.session.authenticate(request.session.db, login, jwt_token)
                    # 登录成功之后清除token密码 保证不破坏原有机制
                    user_id.oauth_access_token = None
                    env.cr.commit()
                    if uid:
                        request.params['login_success'] = True
                    return http.redirect_with_hash(redirect_url)

        error_msg = '当前用户身份信息有误'
        return error_msg

    def _validate_iat(self, payload):
        """
        验证 时间戳
        :param payload:
        :return:
        """
        if 'iat' not in payload.keys():
            errmsg = 'JWT payload中缺少iat参数'
            return errmsg

        if 'exp' not in payload.keys():
            # 默认2小时
            now_stamp = time.time()

            if now_stamp > int(payload.get('iat')) + 7200:
                errmsg = 'Token签名已失效'
                return errmsg

        return True

你可能感兴趣的:(odoo,python)