钉钉扫码登陆的实现 与OAUTH2.0

 

1.1 传统的登陆

举一个例子:有一个"云冲印"的网站,能够将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取本身储存在Google上的照片。数据库

问题是只有获得用户的受权,Google才会赞成"云冲印"读取这些照片。那么,"云冲印"怎样得到用户的受权呢?
传统方法是,用户将本身的Google用户名和密码,告诉"云冲印",后者就能够读取用户的照片了。这样的作法有如下几个严重的缺点json

传统登陆的缺点

(1)"云冲印"为了后续的服务,会保存用户的密码,这样很不安全。
(2)Google不得不部署密码登陆,而咱们知道,单纯的密码登陆并不安全。
(3)"云冲印"拥有了获取用户储存在Google全部资料的权力,用户无法限制"云冲印"得到受权的范围和有效期。
(4)用户只有修改密码,才能收回赋予"云冲印"的权力。可是这样作,会使得其余全部得到用户受权的第三方应用程序所有失效。
(5)只要有一个第三方应用程序被破解,就会致使用户密码泄漏,以及全部被密码保护的数据泄漏。c#

1.2 OAUTH

OAUTH协议为用户资源的受权提供了一个安全的、开放而又简易的标准。与以往的受权方式不一样之处是OAUTH的受权不会使第三方触及到用户的账号信息(如用户名与密码),
即第三方无需使用用户的用户名与密码就能够申请得到该用户资源的受权,所以OAUTH是安全的。oAuth是Open Authorization的简写。api

 

OAUTH原理

我在图上分了四个步骤,下面是四步的讲解:
  第一步:用户访问第三方网站,好比:就是你须要使用QQ进行登陆的网站;
  第二步:你点击QQ登陆后,第三方网站将会链接并进行请求,好比:你点击登陆后,第三方网站会跳转到QQ平台,提示你进行登陆;
  第三步:你要进行受权第三方网站对你的信息访问的一个权限,好比:当你QQ登陆成功后,QQ会提示你,是否受权第三方Web访问你的用户基本信息或其余的资源信息,这时你点击受权便可;
  第四步:受权后,第三方Web便可访问你刚才受权的资源信息,好比:你的QQ基本信息-头像、昵称、性别等。安全

OAUTH2.0 认证流程

第一步:首先直接跳转至用户受权地址,即图示 Request User Url ,提示用户进行登陆,并给予相关资源受权,获得惟一的Auth code,这里注意的是code只有10分钟的有效期  
第二步:获得受权code后,这一步就是请求access token,经过 图示 Request access url ,生成获得数据Token;
 第三步:经过Access Token请求OpenID,OpenID是用户在此平台的惟一标识,经过图示 Request info url 请求,而后获得OpenID;
 第四步:经过第二步获得的数据Token、第三步获得的OpenID及相关API,进行请求,获取用户受权资源信息。服务器

钉钉登陆的实现

钉钉登陆实现的原理其实就是用的OAUTH2.0app

要让你的app实现钉钉的登陆获取登录者相关的信息,你须要作一块儿操做:网站

1.首先你须要登陆钉钉管理员帐号,this

(https://open-doc.dingtalk.com/doc2/detail.htm?treeId=168&articleId=104881&docType=1)url

这是详细操做获取地址网址,

2 c#实现登陆

  1  public ActionResult Index(string url)
  2         {
  3             var s = Request.Url.ToString();
  4             s = s.Replace("code=", "&");
  5             s = s.Replace("&state=", "&");
  6             if (s.Contains("STATE"))
  7             {
  8                 try
  9                 {
 10                     var code = s.Split('&')[1].ToString();
 11                     var access_token = "";
 12 
 13                     #region 使用appid及appSecret访问以下接口,获取accesstoken
 14 
 15                     var uriString = "";
 16                    
 17                      if (s.Contains("服务器ip地址"))
 18                     {
 19                         uriString = @"https://oapi.dingtalk.com/sns/gettoken?appid=dingoaycgdqrrmcvvgde99&appsecret=eKBFq0-0yoWyg9jCWh-K6HiDVh9jP0_0lyOqGhDYfQ8HWb7ZlNUiGnP8JOOP2pSL";
 20                     }
 21                     var uri = new Uri(uriString);
 22                     var req = HttpWebRequest.Create(uri) as HttpWebRequest;
 23                     //设置通用的请求属性
 24                     req.Method = "get";
 25                     req.Host = "oapi.dingtalk.com";
 26                     req.ContentType = "application/Json";
 27                     req.Timeout = 1000 * 30;
 28                     var rsp = this.RequestHttp(req);
 29                     using (Stream stream = rsp.GetResponseStream())
 30                     {
 31                         using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
 32                         {
 33                             var text = reader.ReadToEnd();
 34                             access_token = text.Split(',')[1].ToString().Split(':')[1].ToString();
 35                         }
 36                     }
 37 
 38                     #endregion
 39 
 40                     #region 根据code 和 accesstoken 获取当前钉钉用户受权给你的持久受权码
 41 
 42                     var uriString2 = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token=" + access_token;
 43                     uriString2 = uriString2.Replace("\"", "");
 44                     var uri2 = new Uri(uriString2);
 45                     var req2 = HttpWebRequest.Create(uri2) as HttpWebRequest;
 46                     req2.Method = "Post";
 47                     req2.Accept = "*/*";
 48                     req2.Host = uri2.Authority;
 49                     req2.ContentType = "application/Json";
 50 
 51                     var jsonData = "{\"tmp_auth_code\"" + ":\"" + code + "\"}";
 52 
 53                     byte[] cont = Encoding.UTF8.GetBytes(jsonData);
 54 
 55 
 56                     req2.ContentLength = cont.Length;
 57                     Stream reqStream2 = req2.GetRequestStream();
 58                     reqStream2.Write(cont, 0, cont.Length);
 59 
 60                     var rsp2 = this.RequestHttp(req2);
 61                     var persistentCode = "";
 62                     using (Stream stream2 = rsp2.GetResponseStream())
 63                     {
 64                         using (StreamReader reader = new StreamReader(stream2, Encoding.UTF8))
 65                         {
 66                             var text = reader.ReadToEnd();
 67                             persistentCode = text;
 68                         }
 69                     }
 70 
 71                     #endregion
 72 
 73                     #region 经过永久受权码,获取该用户受权的SNS_TOKEN,此token的有效时间为2小时,重复获取不会续期
 74 
 75                     var uriString3 = "https://oapi.dingtalk.com/sns/get_sns_token?access_token=" + access_token;
 76                     uriString3 = uriString3.Replace("\"", "");
 77                     var uri3 = new Uri(uriString3);
 78                     var req3 = HttpWebRequest.Create(uri3) as HttpWebRequest;
 79                     req3.Method = "Post";
 80                     req3.Accept = "*/*";
 81                     req3.Host = uri3.Authority;
 82                     req3.ContentType = "application/Json";
 83 
 84                     byte[] cont3 = Encoding.UTF8.GetBytes(persistentCode);
 85 
 86 
 87                     req3.ContentLength = cont3.Length;
 88                     Stream reqStream3 = req3.GetRequestStream();
 89                     reqStream3.Write(cont3, 0, cont3.Length);
 90 
 91                     var rsp3 = this.RequestHttp(req3);
 92                     var sns_token = "";
 93                     using (Stream stream3 = rsp3.GetResponseStream())
 94                     {
 95                         using (StreamReader reader = new StreamReader(stream3, Encoding.UTF8))
 96                         {
 97                             var text = reader.ReadToEnd();
 98                             sns_token = text.Split(',')[2].ToString().Split(':')[1].ToString();
 99                         }
100                     }
101 
102                     #endregion
103 
104                     #region 在得到钉钉用户的SNS_TOKEN后,经过如下请求获取该用户的我的信息
105 
106                     var uriString4 = "https://oapi.dingtalk.com/sns/getuserinfo?sns_token=" + sns_token;
107                     uriString4 = uriString4.Replace("\"", "");
108                     var uri4 = new Uri(uriString4);
109                     var req4 = HttpWebRequest.Create(uri4) as HttpWebRequest;
110                     req4.Method = "get";
111                     req4.Accept = "*/*";
112                     req4.Host = uri4.Authority;
113                     req4.ContentType = "application/Json";
114 
115                     var rsp4 = this.RequestHttp(req4);
116                     var userName = "";
117                     using (Stream stream4 = rsp4.GetResponseStream())
118                     {
119                         using (StreamReader reader = new StreamReader(stream4, Encoding.UTF8))
120                         {
121                             var text = reader.ReadToEnd();
122                             userName = text.Split(':')[5].ToString().Split(',')[0].ToString();
123                             userName = userName.Substring(1, userName.Length - 2);//去掉引号
124                         }
125                     }
126 
127                     #endregion
128 
129                     ViewBag.UserName = userName;
130                     var repo = RF.Concrete<DBMUserRepository>();
131                     var user = repo.GetByName(userName);
132                     if (user.Count == 0)
133                     {
134                         DBMUser item = new DBM.DBMUser();
135                         item.Name = userName;
136                         RF.Save(item);
137                     }
138 
139                     ///当数据库没有该用户的时候,数据库为该用户添加数据
140                     var newUser = repo.GetByName(userName)[0];
141                     DBMContext.CurrentUser = newUser;
142                     DBMContext.IsAdmin = newUser.IsAdmin;
143                     return View();
144                 }
145                 catch (Exception e)
146                 {
147                     return null;
148                 }
149             }
150             else
151             {
152                 ViewBag.UserName = "error1";
153                 return View();
154             }
155         }

 

 这样就OK了。

相关文章
相关标签/搜索