.NET MAUI Blazorで構築したアプリを、モバイル環境に適用しよう
マルチターゲットアプリ開発の新しいアプローチ~.NET 9 新テンプレートの基本~ 第4回
ダウンロード サンプルファイル (217.5 KB)
APIキー取得処理の変更(1)
前回は、起動時にユーザーシークレットからAPIキーを読み込む形にしていましたが、今回はこの処理を変更して、プラットフォームごとにAPIキーの取得元を切り替える実装パターンにしてみます。
Web環境ではユーザーシークレットを読み込み、モバイルやWindowsアプリ環境では、SecureStorage(APIキーはソースコード埋め込み)を利用する形とします。
作成するサービスと実装クラスの構成
今回作成するインターフェイスと実装クラスは、次のとおりです。
- IApiKeyStorageインターフェイス:キーの取得場所を抽象化する。取得メソッドのみを定義
- ApiKeyServiceクラス:IApiKeyStorageインターフェイスを使ってキーを取得する
-
ApiKeyStorage実装クラス
- Web: IConfigurationを利用してユーザーシークレットからキーを取得
- Android/Windowsアプリ:SecureStorageからキーを取得。キーがなければソースコード内の定数を(保存後)参照
ApiKeyServiceクラスは、IApiKeyStorageの実装クラスを利用、つまり依存する構成になっています。IApiKeyStorageインターフェイスは、APIキーを取得する処理を抽象化して、実装オブジェクトでプラットフォームごとの分岐を吸収するようにします。実装オブジェクトは、それぞれのプロジェクトで注入される形とします。
インターフェイスの定義
まずは、ImageGenerator.SharedプロジェクトのServicesフォルダに、IApiKeyStorageインターフェイスを新規作成します。ここは、単にキーを取得する非同期メソッドの宣言だけです。
public interface IApiKeyStorage
{
Task<string> GetKeyAsync(); // 非同期で取得
}
共有する実装クラスの作成
次に、各プロジェクトで共有する実装クラスとなるApiKeyServiceクラスを、ImageGenerator.SharedプロジェクトのServicesフォルダに新規作成します。
public class ApiKeyService(IApiKeyStorage storage)
{
public async Task<string> GetApiKeyAsync()
{
// 具体的な保存場所は IApiKeyStorageオブジェクトに任せる
var key = await storage.GetKeyAsync();
if (string.IsNullOrEmpty(key))
{
throw new Exception("not key");
}
return key;
}
}
ApiKeyServiceクラスは、IApiKeyStorageインターフェイスを実装したクラスのメソッドを呼び出すだけです。このようにすると、同じメソッドの呼び出しで、各プロジェクトに応じた処理を切り替えることができます。
Web環境の実装クラスの作成
IApiKeyStorageインターフェイスを実装したWebKeyStorageクラスを、ImageGenerator.WebプロジェクトのServicesフォルダに新規作成します。
public class WebKeyStorage(IConfiguration configuration) : IApiKeyStorage
{
public Task<string> GetKeyAsync()
{
// WebではUserSecrets から取得
var key = configuration["OpenAI:ApiKey"];
return Task.FromResult(key ?? string.Empty);
}
}
これは、ユーザーシークレットから取得する処理です。前回では、ユーザーシークレットのJSON文字列をオブジェクトにマッピングしましたが、今回は、MAUIで用意されているIConfigurationオブジェクトのメソッドを使って、直接、読み出しています。IConfigurationオブジェクトは、フレームワークで注入されるため、明示的に作成する必要はありません。
なお、ImageGenerator.Webプロジェクト用に、ユーザーシークレットを作成する必要があります。ソリューションエクスプローラーでImageGenerator.Webプロジェクトを右クリックし、[ユーザーシークレットの管理]を選択し、前回同様のAPIキーを設定しておきます。
{
"OpenAI": {
"ApiKey": "sk-proj-...."
}
}
モバイル/Windowsアプリ環境の実装クラスの作成
同様に、IApiKeyStorageインターフェイスを実装したMauiKeyStorageクラスを、ImageGeneratorプロジェクトのServicesフォルダに新規作成します。
public class MauiKeyStorage() : IApiKeyStorage
{
private const string ApiKey = "sk-proj-...";
private const string KeyName = "openai_api_key";
public async Task<string> GetKeyAsync()
{
// MAUI固有のSecureStorageを使用
var key = await SecureStorage.GetAsync(KeyName);
if (!string.IsNullOrEmpty(key))
{
return key;
}
await SecureStorage.SetAsync(KeyName, ApiKey);
return ApiKey;
}
}
ここでは、APIキーをソースに埋め込んでいます。これは、あくまで開発用であり、Gitなどのバージョン管理システムにコミットする際は、キー文字列を削除してください。
また、実際の本番環境では、外部にキーが漏れないように、ソース埋め込みではない方法を採用すべきです。本番環境に対応した処理は、次回以降で説明する予定です。
SecureStorageとは
今回利用しているSecureStorageとは、プラットフォーム固有のセキュアな(暗号化された)ストレージ機構をラップしたMAUIのライブラリです。.NET MAUI アプリからは、統一された ISecureStorageインターフェースとして見えますが、内部では各OSのネイティブAPI(Keychain、Keystoreなど)を呼び出しています。開発者が暗号化アルゴリズムや鍵管理を実装しなくても、OSが提供するセキュリティ機能を利用できます。
今回作成したMauiKeyStorageのGetKeyAsyncメソッドでは、SecureStorageで保存されたAPIキーを参照(SecureStorage.GetAsyncメソッド)しています。保存されていない場合は、ソースコード内の定数を保存(SecureStorage.SetAsyncメソッド)して、その値を返します。
SecureStorageのデータ構造は、文字列のみで、いわゆるKey-Value形式です。バイナリなどを保存したい場合は、Base64 エンコードなどで文字列に変換する必要があります。
この記事は参考になりましたか?
- マルチターゲットアプリ開発の新しいアプローチ~.NET 9 新テンプレートの基本~連載記事一覧
- この記事の著者
-
WINGSプロジェクト 高江 賢(タカエ ケン)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
