zoukankan      html  css  js  c++  java
  • openresty钉钉免密登陆

    --- 本次请求是否应该走钉钉登陆逻辑: zkk
    --- 依据UA判定,返回 true 或 false
    
    local luaConfig = require "ding_config"
    local hmac = require "resty.hmac"
    local cjson = require "cjson.safe"
    local http = require "resty.http"
    local t_ = require "tool_"
    local httpc = http.new()
    
    
    
    local appid=luaConfig.ding_account.appid
    local appsecret= luaConfig.ding_account.appsecret
    local AppKey= luaConfig.ding_account.AppKey
    local AppSecret=luaConfig.ding_account.AppSecret
    local call_back=luaConfig.ding_account.call_back
    
    local function post(url,body)
       
        local http = require "resty.http"
          local httpc = http.new()
          local res, err = httpc:request_uri(url, {
                    ssl_verify = false,
                    method = "POST",
                    body = body,
                    headers = {
    --                    ['Content-Type']="application/x-www-form-urlencoded",
                        ['Content-Type']="application/json;charset=UTF-8"
            }
          })
        return res,err
    
    end
    
    local function get(url)
        local res, err = httpc:request_uri(url,
        {
        ssl_verify = false,
        method = "GET",
        body = "",
        headers = {
           ['Content-Type']="application/json;charset=UTF-8"
             }
        })
        return res,err
    end
    
    local function get_tooken_login()
        local res,err=get(string.format("https://oapi.dingtalk.com/sns/gettoken?appid=%s&appsecret=%s",appid,appsecret))
        return res.body
    end
    
    local function get_tooken_glable()
        local res,err=get(string.format("https://oapi.dingtalk.com/gettoken?appkey=%s&appsecret=%s",AppKey,AppSecret))
        return res.body
    end
    
    
    
    local function is_dingding_login()
        --TODO--
        local mobile = {
                    "phone", "android", "mobile", "itouch", "ipod", "symbian", "htc", "palmos", "blackberry", "opera mini", "windows ce", "nokia", "fennec",
                    "hiptop", "kindle", "mot", "webos", "samsung", "sonyericsson", "wap", "avantgo", "eudoraweb", "minimo", "netfront", "teleca"
        }
        local userAgent = ngx.req.get_headers().user_agent
        userAgent = string.lower(userAgent)
        for i, v in ipairs(mobile) do
            if string.match(userAgent, v) and string.match(userAgent, "dingtalk") then
                return true
            end
        end
        return false
    end
    
    --- 将页面重定向到钉钉的后台地址,等待对方回调回来
    local function redirect_to_dingding()
        --TODO
        local uri="https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="..appid.."&response_type=code&scope=snsapi_auth&redirect_uri="..call_back
    --    print(uri)
        ngx.redirect(uri)
    end
    
    local function urlEncode(s)
      s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end)
      return string.gsub(s, " ", "+")
    end
    
    local function temp_code_get_unionid(code)
    
        --时间戳
        local timestamp = ngx.now()*1000
    
        --签名计算
        local app_secret = appsecret
        local hmac_sha256 = hmac:new(app_secret, hmac.ALGOS.SHA256)
            if not hmac_sha256 then
                return false,"failed to create the hmac_sha1 object"
            end
        local ok = hmac_sha256:update(tostring(timestamp))
            if not ok then
                return false,"failed to add data"
            end
        local mac = hmac_sha256:final()  -- binary mac
        local signature=ngx.encode_base64(mac)
        if not hmac_sha256:reset() then
            return false,"failed to reset hmac_sha256"
        end
        local sign = urlEncode(signature)
        -- appid 是创建扫码登陆中的appid
    
        --获取用户信息
        local user_info_url = 'https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='..sign..'&timestamp='..timestamp..'&accessKey='..appid
        local data={tmp_auth_code = code }
        local res,err=post(user_info_url,cjson.encode(data))
        if res == nil or cjson.decode(res.body)['errcode']~=0 then
            return false,"获取用户unionid失败"
        end
        return true,cjson.decode(res.body)["user_info"]["unionid"]
    
    end
    
    local function unionid_get_userid(unionid)
        --获取全局tooken
        local tooken_ret=get_tooken_glable()
        local g_token=nil
        --{"errcode":0,"access_token":"b7e87fc6cced35ff8f01901c5ae0fa6b","errmsg":"ok","expires_in":7200}
        if cjson.decode(tooken_ret)['errcode'] then
             g_token=cjson.decode(tooken_ret)['access_token']
        else
            return false,"全局token 获取失败"
        end
    
        --获取用户钉钉userid
        local uid_url=string.format("https://oapi.dingtalk.com/user/getUseridByUnionid?access_token=%s&unionid=%s",g_token,unionid)
        local uid_res,uid_err=get(uid_url)
        --{"errcode":0,"errmsg":"ok","contactType":0,"userid":"083647406924133856"}
        local ding_uid=nil
        if uid_res==nil or cjson.decode(uid_res.body)["errcode"]~=0 then
            return false,"获取钉钉userid失败"
        else
           ding_uid=cjson.decode(uid_res.body)["userid"]
        end
    
        --获取用户详情
        local user_info_uri=string.format("https://oapi.dingtalk.com/user/get?access_token=%s&userid=%s",g_token,ding_uid)
        local userinfo_res,userinfo_err=get(user_info_uri)
        if userinfo_res==nil or cjson.decode(userinfo_res.body)["errcode"]~=0 then
            return false,"获取用户详情失败"
        else
            local mail=cjson.decode(userinfo_res.body)["email"]
            local mobile=cjson.decode(userinfo_res.body)["mobile"]
            local u_ret={
                mail = mail,
                mobile = mobile,
            }
            return true,u_ret
        end
    end
    
    
    local _M={}
    _M.is_dingding_login=is_dingding_login
    _M.redirect_to_dingding=redirect_to_dingding
    _M.temp_code_get_unionid=temp_code_get_unionid
    _M.unionid_get_userid=unionid_get_userid
    return _M
  • 相关阅读:
    线段树快速查找区间值
    html学习笔记
    区块链是怎么运行的
    【C++ 流类库与输入输出 】实验七
    【C++ 实验六 继承与派生】
    10天冲刺第四天后端app开发
    10天冲刺第三天后端app开发
    10天冲刺第二天之完成后端
    第二次冲刺第一天之后台管理
    第一阶段--冲刺总结
  • 原文地址:https://www.cnblogs.com/zhangkui/p/12887947.html
Copyright © 2011-2022 走看看