使用DotNetOpenAuth搭建OAuth2.0授权框架——Demo代码简单说明

简介: 前段时间随意抽离了一部分代码作为OAuth2的示例代码,若干处会造成困扰,现说明如下: 1 public class OAuthController : Controller 2 { 3 private static string _authorizeUrl = ConfigurationManager.

前段时间随意抽离了一部分代码作为OAuth2的示例代码,若干处会造成困扰,现说明如下:

 1 public class OAuthController : Controller
 2     {
 3         private static string _authorizeUrl = ConfigurationManager.AppSettings["AuthorizeUrl"];
 4         private static string[] _queryParameters = new string[] { "client_id", "redirect_uri", "state", "response_type", "scope" };
 5         private readonly AuthorizationServer _authorizationServer = new AuthorizationServer(new OAuth2AuthorizationServer());
 6         
 7         [AcceptVerbs(HttpVerbs.Get)]
 8         public ActionResult Authorize(string userkey)
 9         {
10             var pendingRequest = this._authorizationServer.ReadAuthorizationRequest(Request);
11             if (pendingRequest == null)
12             {
13                 throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
14             }
15 
16             if (string.IsNullOrEmpty(userkey))
17             {
18                 string url = _authorizeUrl, callback = Request.Url.GetLeftPart(UriPartial.Path);
19                 StringBuilder querystring = new StringBuilder(string.Format("client_id={0}&", HttpUtility.UrlEncode(this.Request.QueryString["client_id"]))), callbackQuery = new StringBuilder();
20                 foreach (string key in this.Request.QueryString.Keys)
21                 {
22                     if (!_queryParameters.Contains(key))
23                         querystring.Append(string.Format("{0}={1}&", key, HttpUtility.UrlEncode(this.Request.QueryString[key])));
24                     else
25                         callbackQuery.Append(string.Format("{0}={1}&", key, HttpUtility.UrlEncode(this.Request.QueryString[key])));
26                 }
27                 if (callbackQuery.Length > 0)
28                 {
29                     callback += ("?" + callbackQuery.ToString().TrimEnd('&'));
30                     querystring.Append(string.Format("callback={0}&", HttpUtility.UrlEncode(callback)));
31                 }
32                 if (querystring.Length > 0)
33                 {
34                     url += ("?" + querystring.ToString().TrimEnd('&'));
35                 }
36                 return Redirect(url);
37             }
38             else
39             {
40                 using (var db = new OAuthDbContext())
41                 {
42                     var client = db.Clients.FirstOrDefault(o => o.ClientIdentifier == pendingRequest.ClientIdentifier);
43                     if (client == null)
44                         throw new AuthorizeException("40143", "不受信任的商户");
45                     else
46                     {
47                         var user = DESCrypt.Decrypt(userkey, client.ClientSecret);
48                         var approval = this._authorizationServer.PrepareApproveAuthorizationRequest(pendingRequest, user);
49                         var response = this._authorizationServer.Channel.PrepareResponse(approval);
50                         return response.AsActionResult();
51                     }
52                 }
53             }
54         }
55 
56         public ActionResult Index()
57         {
58             ViewBag.Body = "Welcome To OAuth2.0";
59             return View();
60         }
61     }

这是授权服务端的主要代码。AuthorizeUrl和userkey分别表示什么意思?

这里涉及到我所在公司的具体情况,简单地说,用户授权的具体逻辑是由另外单独的站点(AuthorizeUrl表示,为方便描述,称为A站点)引导,所以这里的代码主要起到一个跳转的作用。我们看DotNetOpenAuth的官方Demo,会发现授权服务端有登录页面、授权页面等等,其实本质是一样的,只是拆分成两个站点。除了OAuth参数,此处可能会传递其它参数,所以使用_queryParameters来区分,并分别构建两部分查询字符串,OAuth参数会附加到callback地址参数上,用户授权后会从A站点跳回该地址(此处就是该action所表示的地址),然后返回浏览器授权码。

关于userkey,大家看到有个解密的步骤(第47行),so,这肯定是考虑到安全问题。公司的业务逻辑大多采用userid标示用户,为自增长int类型,用户通过A站点授权后通过浏览器callback时,userid可以在地址栏中被捕捉到,假如复制该地址并随意更改userid值,就很有可能在对应用户未授权的情况下获得其访问权限。所以我们不允许直接传递userid,而是经过一层对称加密,这就是userkey的由来。如果授权逻辑并未拆分成独立站点,那么就不存在这种情况了。

 

后续我可能会再补充若干内容,由于工作较忙,只对有朋友提出疑问的地方做一说明;若有其它问题,请告知,我会不定期更新。

目录
相关文章
|
C语言
[字符串和内存函数]strcmp和strncmp以及memcmp的区别
[字符串和内存函数]strcmp和strncmp以及memcmp的区别
395 0
|
Web App开发 JavaScript 前端开发
Vue上传图片裁剪预览插件vue-img-cutter的使用
Vue上传图片裁剪预览插件vue-img-cutter的使用
655 0
|
6月前
|
算法 数据建模 应用服务中间件
阿里云2025智惠采购季,WoSign SSL证书优惠叠加使用攻略
阿里云2025智惠采购季,WoSign SSL证书折上折满减优惠!活动月期间(2025年03月01日至03月31日)活动折扣叠加满减优惠券,具体如何操作才能获取组合优惠价格呢?快来get优惠券组合使用攻略吧!
560 4
|
11月前
|
存储 关系型数据库 MySQL
mysql的begin end嵌套
本文介绍了MySQL中如何使用`begin`和`end`关键字进行事务或存储过程的嵌套操作,并强调了编写嵌套代码时需要注意作用域的重要性。
148 0
mysql的begin end嵌套
|
开发框架 NoSQL 前端开发
在Winform项目和Web API的.NetCore项目中使用Serilog 来记录日志信息
在Winform项目和Web API的.NetCore项目中使用Serilog 来记录日志信息
|
网络协议 Dubbo Java
什么是RPC?RPC和HTTP对比?RPC有什么缺点?市面上常用的RPC框架?
选择合适的RPC框架和通信协议,对于构建高效、稳定的分布式系统至关重要。开发者需要根据自己的业务需求和系统架构,综合考虑各种因素,做出适宜的技术选型。
1244 1
|
存储 安全 Unix
C#.Net筑基-类型系统②常见类型--日期和时间的故事
在System命名空间中,有几种表示日期时间的不可变结构体(Struct):DateTime、DateTimeOffset、TimeSpan、DateOnly和TimeOnly。DateTime包含当前本地或UTC时间,以及最小和最大值;DateTimeOffset增加了时区偏移信息,适合跨时区操作。UTC是世界标准时间,而格林尼治标准时间(GMT)不稳定,已被更精确的UTC取代。DateTimeOffset和DateTime提供了转换为UTC和本地时间的方法,以及各种解析和格式化函数。
201 5
|
安全 前端开发 JavaScript
防御点击劫持:X-Frame-Options头的重要性与实践
防御点击劫持:X-Frame-Options头的重要性与实践
1826 0
|
API 开发工具 对象存储
网站文件名使用了中文字符并且在上传到 OSS 后无法打开
网站文件名使用了中文字符并且在上传到 OSS 后无法打开
1336 2
|
缓存 NoSQL 数据可视化
Mac下安装与使用Medis
Mac下安装与使用Medis
359 0