关于提供第三方接口一键登录

    有时候需要对接第三方系统,通过数据同步的手段实现一键登录功能,比如学校学生管理网站迁入到教育局官网/ 校园网站,这些不同网站之间实现用户共享,即从A平台可以跳转到B平台, 实现自动登录的机制,对于系统而言,提供一个第三方登录的接口,映射到外网,然后根据双方约定的加密方式,进行参数的一系列解密,解析,验证,通过后最后跳转到系统中,不通过则跳转到友好界面。

       public ActionResult CypressLogin(string encryp)    
    {         
    try         
  {           
if (string.IsNullOrEmpty(encryp)) { return RedirectToAction("Err_500Param", "Index", new { Content = "参数找不到" }); } //解密参数 3DES帮助类 var encry = DESHelper.DESDecrypt(encryp, Confighelper.GetValue("CryKey")); if (encry == "参数有误") { return RedirectToAction("Err_500Param", "Index", new { Content = encry }); } //解析参数-构造参数类实体 var desAry = encry.Split('*'); var desModel = ParamHelper.GetModel<CryParamsModel>(desAry); //判断参数值是否为null,反射实体所在字段 Type type = desModel.GetType(); PropertyInfo[] props = type.GetProperties(); var val = props.Where(c => c.GetValue(desModel).ToStr() == string.Empty).Select(c => "参数: " + c.Name + "不能为Null").FirstOrDefault(); if (val != null) { return RedirectToAction("Err_500Param", "Index", new { Content = val }); } //判断请求是否过期(保证请求时间在1分钟内) var t1 = new TimeSpan(long.Parse(desModel.Time)); var t2 = new TimeSpan(DateTime.Now.Ticks); if (Math.Abs(t1.Subtract(t2).Minutes) != 0 && Math.Abs(t1.Subtract(t2).Minutes) != 1) { return RedirectToAction("Err_500Param", "Index", new { Content = "请求时间已过期" }); } //验证用户是否正确,数据库检索用户信息 var res = userbll.EryLogin(desModel.uType, desModel.NO); if (res.UserCode == "") { return RedirectToAction("Err_500Param", "Index", new { Content = "用户名和账号不匹配" }); }
//注入用户缓存
//... ...
//跳转指定路径 return Redirect("/Admin/Index/MasterIndex"); } catch (Exception ex) { return RedirectToAction("Err_500Param", "Index", new { Content = "请求失败,参数异常" }); } }

其中,对于解密后的字符串参数,多数带有一些分隔符号,这里用一个通用方法中进行处理,最后序列化为实体对象,供方便使用

        public static T GetModel<T>(string[] aryParam, char type = '=')
        {
            try
            {
                var dic = new Dictionary<string, string>();
                foreach (string s in aryParam)
                {
                    var pair = s.Split(type);
                    var name = pair[0];
                    var value = pair.Length > 1 ? pair[1] : string.Empty;
                    dic.Add(name, value);
                }
                var json = JsonConvert.SerializeObject(dic);
                return JsonConvert.DeserializeObject<T>(json);
            }
            catch (Exception)
            {
                return default(T);
            }
        }

总体而言,一个是解析,一个验证,同时做好友好界面的跳转,这里看上去没什么技术含量,流程上也没有什么精妙的设计,权当做个记录,指不定哪天灵光一闪,便有更好的思路

附上一个API权限验证的过滤器

 public override void OnAuthorization(HttpActionContext actionContext)
        {
            #region 获取请求参数
            dynamic dynamic = null;
            string parmethod = actionContext.Request.Method.Method;
            if (parmethod.ToLower() == "post" && !actionContext.Request.Content.IsFormData())
            {
                var definition = new { AppId = "", TimeStamp = "", Sign = "" };
                string strData = actionContext.Request.Content.ReadAsStringAsync().Result;
                dynamic = JsonConvert.DeserializeAnonymousType(strData, definition);
            }
            else
            {
                dynamic = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);
            }
            #endregion

            #region 校验参数
            if (dynamic == null)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, new HttpError("缺少签名等验证参数"));
                return;
            }
            var dic = new Dictionary<string, string>
            {
                { "AppId", dynamic["appId"] },
                { "TimeStamp", dynamic["TimeStamp"] },
                { "Sign", dynamic["sign"] }
            };
            //验证参数签名
            foreach (var item in dic)
            {
                if (string.IsNullOrEmpty(item.Value))
                {
                    actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, new HttpError("缺少参数:" + item.Key));
                    return;
                }
            }
   
            #endregion

            #region 验证AppId 和签名
            var responModel = new ResponseSalaryModel();
            JObject jsonSendObj = new JObject
            {
                {"Type", "GetAppAppId"},
                {"APPID",dic["AppId"] }
            };
            var connStr = CachedConfigContext.Current.DBConfig.DbConnectString;
            var jsonRevObj = new SqlDAL.System().GetAppJoinByAppId(connStr, jsonSendObj, null);
            var obj = JsonConvert.DeserializeObject<JObject>(jsonRevObj)["Data"].ToString();
            var app = JsonConvert.DeserializeObject<AppJoinModel>(obj);
            if (app == null)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, new HttpError("data error, appId not found"));
                return;
            }
            var mix = dic["AppId"] + app.APPSecret + dic["TimeStamp"];
            var bol = dic["Sign"].Equals(Utils.SHA1_Hash(mix));
            if (!bol)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, new HttpError("sign error"));
                return;
            }

            #endregion
            
        }

 

posted @ 2020-09-11 12:27  郎中令  阅读(559)  评论(0编辑  收藏  举报