举一个例子:有一个"云冲印"的网站,能够将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取本身储存在Google上的照片。数据库
问题是只有获得用户的受权,Google才会赞成"云冲印"读取这些照片。那么,"云冲印"怎样得到用户的受权呢?
传统方法是,用户将本身的Google用户名和密码,告诉"云冲印",后者就能够读取用户的照片了。这样的作法有如下几个严重的缺点json
(1)"云冲印"为了后续的服务,会保存用户的密码,这样很不安全。
(2)Google不得不部署密码登陆,而咱们知道,单纯的密码登陆并不安全。
(3)"云冲印"拥有了获取用户储存在Google全部资料的权力,用户无法限制"云冲印"得到受权的范围和有效期。
(4)用户只有修改密码,才能收回赋予"云冲印"的权力。可是这样作,会使得其余全部得到用户受权的第三方应用程序所有失效。
(5)只要有一个第三方应用程序被破解,就会致使用户密码泄漏,以及全部被密码保护的数据泄漏。c#
OAUTH协议为用户资源的受权提供了一个安全的、开放而又简易的标准。与以往的受权方式不一样之处是OAUTH的受权不会使第三方触及到用户的账号信息(如用户名与密码),
即第三方无需使用用户的用户名与密码就能够申请得到该用户资源的受权,所以OAUTH是安全的。oAuth是Open Authorization的简写。api
我在图上分了四个步骤,下面是四步的讲解:
第一步:用户访问第三方网站,好比:就是你须要使用QQ进行登陆的网站;
第二步:你点击QQ登陆后,第三方网站将会链接并进行请求,好比:你点击登陆后,第三方网站会跳转到QQ平台,提示你进行登陆;
第三步:你要进行受权第三方网站对你的信息访问的一个权限,好比:当你QQ登陆成功后,QQ会提示你,是否受权第三方Web访问你的用户基本信息或其余的资源信息,这时你点击受权便可;
第四步:受权后,第三方Web便可访问你刚才受权的资源信息,好比:你的QQ基本信息-头像、昵称、性别等。安全
第一步:首先直接跳转至用户受权地址,即图示 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了。