zoukankan      html  css  js  c++  java
  • DotNetOpenAuth实践之搭建验证服务器

    系列目录:

    DotNetOpenAuth实践系列(源码在这里)

    DotNetOpenAuth是OAuth2的.net版本,利用DotNetOpenAuth我们可以轻松的搭建OAuth2验证服务器,不废话,下面我们来一步步搭建验证服务器

    本次搭建环境:

    .net4.5.1 ,DotNetOpenAuth v5.0.0-alpha3,MVC5

    一、环境搭建

      1、新建一个空的VS解决方案

      2、添加验证服务器项目,项目选择MVC,不要自带的身份验证

      3、使用Nuget添加DotNetOpenAuth v5.0.0-alpha3

    输入DotNetOpenAuth 安装DotNetOpenAuth v5.0.0-alpha3

    添加完成后

    二、编写DotNetOpenAuth 验证服务器关键代码,实现功能

      1、添加AuthorizationServerConfiguration.cs

    这里的配置是为了添加方便管理,其实可以不用这个类

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Security.Cryptography.X509Certificates;
     5 using System.Web;
     6 
     7 namespace IdefavAuthorizationServer.Code
     8 {
     9     /// <summary>
    10     /// 验证服务器配置
    11     /// </summary>
    12     public class AuthorizationServerConfiguration
    13     {
    14         /// <summary>
    15         /// 构造函数
    16         /// </summary>
    17         public AuthorizationServerConfiguration()
    18         {
    19             TokenLifetime = TimeSpan.FromMinutes(5);
    20         }
    21 
    22         /// <summary>
    23         /// 签名证书
    24         /// </summary>
    25         public X509Certificate2 SigningCertificate { get; set; }
    26 
    27         /// <summary>
    28         /// 加密证书
    29         /// </summary>
    30         public X509Certificate2 EncryptionCertificate { get; set; }
    31 
    32         /// <summary>
    33         /// Token有效时间
    34         /// </summary>
    35         public TimeSpan TokenLifetime { get; set; }
    36     }
    37 }

    2、实现IClientDescription接口

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Web;
     5 using DotNetOpenAuth.Messaging;
     6 using DotNetOpenAuth.OAuth2;
     7 
     8 namespace IdefavAuthorizationServer.Code
     9 {
    10     public class Client : IClientDescription
    11     {
    12         /// <summary>
    13         /// 客户端名称client_id
    14         /// </summary>
    15         public string Name { get; set; }
    16 
    17         /// <summary>
    18         /// 客户端类型
    19         /// </summary>
    20         public int ClientType { get; set; }
    21 
    22         /// <summary>
    23         /// 回调URL
    24         /// </summary>
    25         public string Callback { get; set; }
    26 
    27         public string ClientSecret { get; set; }
    28 
    29 
    30         Uri IClientDescription.DefaultCallback
    31         {
    32             get { return string.IsNullOrEmpty(this.Callback) ? null : new Uri(this.Callback); }
    33         }
    34 
    35 
    36         ClientType IClientDescription.ClientType
    37         {
    38             get { return (ClientType)this.ClientType; }
    39         }
    40 
    41 
    42         bool IClientDescription.HasNonEmptySecret
    43         {
    44             get { return !string.IsNullOrEmpty(this.ClientSecret); }
    45         }
    46 
    47 
    48         bool IClientDescription.IsCallbackAllowed(Uri callback)
    49         {
    50             if (string.IsNullOrEmpty(this.Callback))
    51             {
    52                 // No callback rules have been set up for this client.
    53                 return true;
    54             }
    55 
    56             // In this sample, it's enough of a callback URL match if the scheme and host match.
    57             // In a production app, it is advisable to require a match on the path as well.
    58             Uri acceptableCallbackPattern = new Uri(this.Callback);
    59             if (string.Equals(acceptableCallbackPattern.GetLeftPart(UriPartial.Authority), callback.GetLeftPart(UriPartial.Authority), StringComparison.Ordinal))
    60             {
    61                 return true;
    62             }
    63 
    64             return false;
    65         }
    66 
    67 
    68         bool IClientDescription.IsValidClientSecret(string secret)
    69         {
    70             return MessagingUtilities.EqualsConstantTime(secret, this.ClientSecret);
    71         }
    72 
    73 
    74     }
    75 }

    3、实现IAuthorizationServerHost接口

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Security.Cryptography;
     5 using System.Web;
     6 using DotNetOpenAuth.Messaging.Bindings;
     7 using DotNetOpenAuth.OAuth2;
     8 using DotNetOpenAuth.OAuth2.ChannelElements;
     9 using DotNetOpenAuth.OAuth2.Messages;
    10 
    11 namespace IdefavAuthorizationServer.Code
    12 {
    13     public class IdefavAuthorizationServerHost : IAuthorizationServerHost
    14     {
    15         /// <summary>
    16         /// 配置
    17         /// </summary>
    18         private readonly AuthorizationServerConfiguration _configuration;
    19 
    20         /// <summary>
    21         /// 构造函数
    22         /// </summary>
    23         /// <param name="config"></param>
    24         public IdefavAuthorizationServerHost(AuthorizationServerConfiguration config)
    25         {
    26             if (config != null)
    27                 _configuration = config;
    28         }
    29 
    30         /// <summary>
    31         /// Token创建
    32         /// </summary>
    33         /// <param name="accessTokenRequestMessage"></param>
    34         /// <returns></returns>
    35         public AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage)
    36         {
    37             var accessToken = new AuthorizationServerAccessToken();
    38             accessToken.Lifetime = _configuration.TokenLifetime;//设置Token的有效时间
    39 
    40             // 设置加密公钥
    41             accessToken.ResourceServerEncryptionKey =
    42                 (RSACryptoServiceProvider)_configuration.EncryptionCertificate.PublicKey.Key;
    43             // 设置签名私钥
    44             accessToken.AccessTokenSigningKey = (RSACryptoServiceProvider)_configuration.SigningCertificate.PrivateKey;
    45 
    46             var result = new AccessTokenResult(accessToken);
    47             return result;
    48         }
    49 
    50         public IClientDescription GetClient(string clientIdentifier)
    51         {
    52             // 这里需要去验证客户端发送过来的client_id
    53             if (string.Equals(clientIdentifier, "idefav", StringComparison.CurrentCulture))// 这里为了简明起见没有使用数据库
    54             {
    55                 var client=new Client
    56                 {
    57                     Name = "idefav",
    58                     ClientSecret = "1",
    59                     ClientType = 1
    60                 };
    61                 return client;
    62             }
    63             throw new ArgumentOutOfRangeException("clientIdentifier");
    64         }
    65 
    66         public bool IsAuthorizationValid(IAuthorizationDescription authorization)
    67         {
    68             return true;
    69         }
    70 
    71         public AutomatedUserAuthorizationCheckResponse CheckAuthorizeResourceOwnerCredentialGrant(string userName, string password,
    72             IAccessTokenRequest accessRequest)
    73         {
    74             throw new NotImplementedException();
    75         }
    76 
    77         public AutomatedAuthorizationCheckResponse CheckAuthorizeClientCredentialsGrant(IAccessTokenRequest accessRequest)
    78         {
    79             AutomatedUserAuthorizationCheckResponse response = new AutomatedUserAuthorizationCheckResponse(accessRequest, true, "test");
    80             return response;
    81         }
    82 
    83         public ICryptoKeyStore CryptoKeyStore { get; }
    84         public INonceStore NonceStore { get; }
    85 
    86        
    87     }
    88 }

    4、实现OAuthController

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Threading.Tasks;
     5 using System.Web;
     6 using System.Web.Mvc;
     7 using DotNetOpenAuth.Messaging;
     8 using DotNetOpenAuth.OAuth2;
     9 using IdefavAuthorizationServer.Code;
    10 
    11 namespace IdefavAuthorizationServer.Controllers
    12 {
    13     public class OAuthController : Controller
    14     {
    15         private readonly AuthorizationServer authorizationServer =
    16            new AuthorizationServer(new IdefavAuthorizationServerHost(Common.Configuration));
    17 
    18         public async Task<ActionResult> Token()
    19         {
    20             var response = await authorizationServer.HandleTokenRequestAsync(Request);
    21             return response.AsActionResult();
    22         }
    23     }
    24 }

    5、初始化AuthorizationServerConfiguration

    这里采用Windows签名证书

    放到项目中

    制作证书事注意:要加上-a sha1  -sky exchange

    到此,基本代码就写完了,现在说说要注意的地方,OAuth2默认设置的请求是要求SSL的也就是必须是https//localhost:1111/OAuth/Token,然后我们现在不需要使用SSL加密请求,更改一下WebConfig文件

    在WebConfig里面设置成如图中那样,就可以不用https访问了

    6、我们F5运行项目

    使用Post工具发送Post请求访问 http://localhost:53022/OAuth/token 

    Body参数:

    1 client_id:idefav
    2 client_secret:1
    3 grant_type:client_credentials

    请求结果:

    这样我们就拿到了access_token,通过这个access_token我们就可以访问资源服务器了

    更新:

    OAuthController代码添加内容类型

     1 using System.Collections.Generic;
     2 using System.Linq;
     3 using System.Threading.Tasks;
     4 using System.Web;
     5 using System.Web.Mvc;
     6 using System.Web.Script.Services;
     7 using DotNetOpenAuth.Messaging;
     8 using DotNetOpenAuth.OAuth2;
     9 using IdefavAuthorizationServer.Code;
    10 
    11 namespace IdefavAuthorizationServer.Controllers
    12 {
    13     public class OAuthController : Controller
    14     {
    15         private readonly AuthorizationServer authorizationServer =
    16            new AuthorizationServer(new IdefavAuthorizationServerHost(Common.Configuration));
    17         
    18         public async Task<ActionResult> Token()
    19         {
    20             var response = await authorizationServer.HandleTokenRequestAsync(Request);
    21             Response.ContentType = response.Content.Headers.ContentType.ToString();
    22             return response.AsActionResult();
    23         }
    24     }
    25 }

    鉴于有人不知道Windows签名制作,下篇我们一起来看看如何制作一个认证服务器可以使用的签名证书

  • 相关阅读:
    GCC/gcc/g++/CC/cc区别
    C++静态库与动态库(转)
    Linux中find的使用(转)
    “《编程珠玑》(第2版)第2章”:B题(向量旋转)
    第一部分 DotNET与C#概述
    第一部分 二进制
    第一部分 计算机编程语言
    第一部分 计算机常识
    C# 泛型初探
    WPF 实现验证码功能
  • 原文地址:https://www.cnblogs.com/idefav2010/p/DotNetOpenAuth.html
Copyright © 2011-2022 走看看