これは Delphi Advent Calendar の補欠記事です。
API キー
近年のアプリは他のサービスと連携することが当たり前です。
アプリからあるサービス(API)を利用したいとなったら、そのサービスから「キー」(以下 API キー)を提供して貰うことが多いと思います。
このキーはアプリや個人と結びつくもののため公開してはなりません。
個人で開発しているだけなら良いのですが、ライブラリとして公開したり、サンプルとして公開する場合、API キーを悪用されてしまうかもしれません。
API キーの分離
ということで、API キーは分離すべきなのですが、どうやって分離しようかと考えると、例えば
unit KeyConsts;
interface
const
API_KEY = 'AE58E0CC-9653-4363-B622-34544D0DE914'
implementation
end.
というユニットを作って、このユニット KeyConsts.pas を .gitignore に追加してアップを防ぐとかです。
まあ、これでも全然良いのですが…
個人的には $I を使っています。
$I コンパイラ指令
$I コンパイラ指令で指定されたファイルは、$I コンパイラ指令の直後に挿入されます。
これを使うとキーをキーだけで分離できます。
unit KeyConsts;
interface
const
API_KEY = {$I FooApi.Key};
implementation
end.
'AE58E0CC-9653-4363-B622-34544D0DE914'
こんな風に分離して FooApi.Key を .gitignore に追加します。
もしくは、サンプルとして下記の様なダミーの FooApi.Key を入れておいても良いかもしれません。
'YOUR_API_KEY'
この場合、もしも FooApi.Key の中身が変更されていない時にエラーで停止できます。
unit KeyConsts;
interface
const
API_KEY = {$I FooApi.Key};
{$IF API_KEY = 'YOUR_API_KEY'}
{$MESSAGE FATAL 'Foo API のキーを FooApi.Key に記述してください'}
{$ENDIF}
implementation
end.
ただ、これをやるとうっかり本当のキーが書かれた FooApi.Key をアップしてしまうかもしれない諸刃の剣です。
なので、アップしないのが一番でしょう(FooApi.Key が存在しなければコンパイルエラーになるので同じ事です)。
AndroidManifest.xml
そんな感じで $I を使えば API キーを分離できますが、AndroidManifest.xml に記述するタイプのキーとかは中身を置換するのが良いと思います。
Delphi のビルドシステムは MSBuild なので「ビルド前イベント」でバッチファイルや exe を実行できるので、次のようなコンソールアプリを作って
program ReplaceAPIKey;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.Classes, System.SysUtils, System.IOUtils;
const
MANIFEST = 'AndroidManifest.template.xml';
ORG_MANIFEST = '_' + MANIFEST;
API_KEY = 'FooApi.Key'; // 読み込みたい API Key ファイル
TARGET = '%API_KEY%'; // API Key を書き込む Place Holder
var
APIKey: String;
begin
if not TFile.Exists(ORG_MANIFEST) then
TFile.Copy(MANIFEST, ORG_MANIFEST);
TFile.Copy(ORG_MANIFEST, MANIFEST, True);
with TStringList.Create do
try
LoadFromFile(API_KEY);
APIKey := Text.Trim;
LoadFromFile(MANIFEST, TEncoding.UTF8);
Text := Text.Replace(Target, APIKEy);
SaveToFile(MANIFEST, TEncoding.UTF8);
finally
DisposeOf;
end;
end.
ビルド前イベントに追加します。
もちろん、AndrodManifest.template.xml の方も置き換えるのを忘れないでください。
<meta-data android:name="foo.api.key" android:value="%API_KEY%" />
こんな風にしておくと、ビルド前に自動的に置き換わります。
ただし、注意したいのは Google Map の API キーだけは特別扱いで IDE から設定できます。
なので、IDE から設定したキーが記述されている .dproj をアップするとキーも漏洩してしまいます。
これについては悩ましい所ですが、上の仕組みを使って回避するのが良いでしょう。
まとめ
あとは、適当に上手いことやってください!(酷い)