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我們就可以訪問資源服務器了

