.NET開発ノート(二十)認証が必要なサードパーティコンポーネントの作成

認証が必要なソフトウェアを使用する際、登録費用はソフトウェアの利用者ではなく、開発者が支払うケースが多いです。同様に、開発者が日常的に使用するサードパーティコンポーネントも、利用料金を支払う必要があり、この場合の支払い主体は開発者であり、システムの最終利用者ではありません。

この二つの違いは以下の図のように表されます:

図1

本記事では.NET環境において認証が必要なサードパーティコントロールの開発方法について説明します。認証対象が開発者であることを前提として、認証の入口は開発者向けに提供し、最終ユーザーには見えないようにする必要があります。また、一般的に一度の認証は一つの開発者のみに許可されるため、認証情報は開発者のマシンと紐づける必要があります。これはハードウェア識別子との連携によって実現できます。ソフトウェアの公開後は、サードパーティコンポーネントがユーザーの使用に影響を与えてはならず、つまり公開後のコンポーネントは特定のマシンにバインドされることはできません。まとめると以下の点が重要です:

  • コンポーネントの認証料金は、そのコンポーネントを使用してソフトウェアを開発する人に対して請求される;
  • コンポーネントの認証はマシンに紐づけられ、一度の認証は一人の開発者のみが利用できる;
  • ソフトウェアが公開された後は、コンポーネントが最終ユーザーに影響を与えてはならない。認証エントリは最終ユーザーには透明状態でなければならない。

これら三つの問題を解決するために、「デザイン時(Design-Time)」と「ランタイム時(Run-Time)」という重要な概念を理解する必要があります。それらの違いと関係性を把握することが求められます。

これまでのシリーズブログで学んだ通り:

**任意のコンポーネントは「デザイン時」と「ランタイム時」の二つの状態を持ちます。デザイン時とは、コンポーネントがフォームデザイナー内に存在するときの状態です。一方、ランタイム時はアプリケーションが実行されているときの状態です。同じコンポーネントでも、デザイン時とランタイム時の挙動は異なる可能性があります。まるで同じ人物が父親と息子の前で振る舞いが違うように、コンポーネントも状況によって挙動が変わるのです。**簡潔なコード例を示します:

 1 class Component
 2 {
 3 public Component()
 4 {
 5     if (DesignTime)
 6     {
 7          // デザイン時処理
 8     }
 9     else
10     {
11          // ランタイム時処理
12     }
13 }
14 public void DoSomething()
15 {
16    if (DesignTime)
17 {
18     // デザイン時処理
19 }
20 else
21 {
22    // ランタイム時処理
23 }
24 }
25 }

View Code 上記コードのように、ソフトウェア開発段階では開発者がコンポーネントをフォームデザイナー上でインスタンス化する際に、現在のマシンでの認証状態(認証済み、試用期間、期限切れなど)を確認できます。この認証チェックは、現在のマシンのハードウェア情報を基に行われます。ソフトウェアが公開された後は、コンポーネントはデザイナー外にあり、最終ユーザーを対象とするため、通常は認証状態を確認する必要はありません。しかし、開発者が試用版のコンポーネントを使ってソフトウェアをリリースするのを防ぐために、公開後にもコンポーネントの認証状態を確認する必要があります。この際の認証方法はハードウェア情報と関連付ける必要はありません。

本デモでは待機用のプログレスバーを作成しました。このコンポーネントを使用するには認証が必要です。認証時には生成された申請コード(ローカルディスク番号と関連付け)を元に、コンポーネント開発元のアクティベーションコードと照合します。一致すれば認証成功となり、そうでなければ30日間の試用期間が与えられます。試用期間中はインターフェースに試用表示が表示され、期限が過ぎるとコンポーネントは使用できなくなります。公開する場合は、コンポーネントのメソッドを呼び出して申請コードとアクティベーションコードを渡すことで認証を行い、認証成功時は正常に動作し、失敗時は未認証表示が行われます(ただし最終ユーザーには認証を要求しません)。

コンポーネントの現在状態を判定するメソッド:

 1  /// <summary>
 2         /// コンポーネントの状態を確認
 3         /// </summary>
 4         void CheckStatus()
 5         {
 6             ISelectionService isp = GetService(typeof(ISelectionService)) as ISelectionService; //サービス取得
 7 // 同じコンポーネントでも状態によって挙動が異なる
 8             if (isp == null) // 公開時(またはランタイム時)
 9             {
10 // 特に何もしない
11             }
12             else // 開発時(またはデザイン時)
13             {
14                 if (AuthorizeHelper.CheckActivateCode(Properties.Settings.Default.ActivateCode, LocalMachine.GetAskCode())) // 認証状態をチェック
15                 {
16                     currentStatus = 1; // 開発時認証済み
17                 }
18                 else
19                 {
20                     using (frmAuthority frma = new frmAuthority()) // 認証ダイアログ
21                     {
22                         if (frma.ShowDialog() == DialogResult.OK) // 認証成功
23                         {
24                             currentStatus = 1;
25                         }
26                         else
27                         {
28                             if ((DateTime.Now - Properties.Settings.Default.TrialStart).TotalDays >= 30) // 試用期間終了判定
29                             {
30                                 // 例外を投げる
31                                 throw new Exception("ProgressBarコンポーネントが認証されていません!");
32                             }
33                             else
34                             {
35                                 currentStatus = 0; // 開発時試用
36                             }
37                         }
38                     }
39                 }
40             }
41         }

View Code 公開後、申請コードとアクティベーションコードを渡してコンポーネントを認証する:

 1 /// <summary>
 2         /// 公開時の認証エントリポイント
 3         /// </summary>
 4         /// <param name="askCode"></param>
 5         /// <param name="activateCode"></param>
 6         public void UnLock(string askCode, string activateCode)
 7         {
 8             if (AuthorizeHelper.CheckActivateCode(activateCode, askCode)) // 有効性を確認
 9             {
10                 currentStatus = 3; // 開発時(ランタイム時)認証済み
11             }
12             else
13             {
14                 currentStatus = 2; // 開発時(ランタイム時)試用
15             }
16         }

View Code 注:本記事は主にサードパーティコンポーネントの認証原理について述べており、認証方式の安全性については今後の改善が必要です。

デモプロジェクト構造:

図2

表示効果:

1)開発段階におけるコンポーネント認証画面

図3

2)開発段階におけるProgressBarの試用期間

図4

3)公開後の認証されていないProgressBar

図5

4)開発段階における認証成功

図6

ソースコードダウンロードリンク:https://files.cnblogs.com/xiaozhi_5638/ComponentCopyProtection.rar

ご参考になれば幸いです!

タグ: .NET コンポーネント開発 認証システム デザイン時 ランタイム時

5月30日 09:36 投稿