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


    前段时间随意抽离了一部分代码作为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的由来。如果授权逻辑并未拆分成独立站点,那么就不存在这种情况了。

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

  • 相关阅读:
    mysql关联查询
    MySQL数据库面试题(转发来自https://thinkwon.blog.csdn.net/article/details/104778621)
    iview + vue + thinphp5.1 源码
    <!--标签嵌套规则-->
    PHP的基本变量检测方法
    PHP的八种变量
    php变量命名规范
    C++11新特性-常用
    算法设计-DP常见问题及解题技巧
    Web开发-概述
  • 原文地址:https://www.cnblogs.com/newton/p/3680154.html
Copyright © 2020-2023  润新知