.NET Framework 4.5 (WIF 4.5) を使用した Active Authentication については、「.NET 4.5 で Active Authentication を実装する」に記載しました。
環境 : AD FS 2.0 (Active Directory Federation Services 2.0), Windows Azure Active Directory – Access Control Service 2.0, Visual Studio 2010, Windows Azure SDK for .NET 1.6, WIF SDK 3.5 (Windows Identity Foundation SDK 3.5)
AD FS 2.0 フェデレーションを処理する Client Programming (Active Authentication)
- Windows Azure Active Directory – ACS 編
- Office 365 – Microsoft Federation Gateway 編
こんにちは。
Microsoft 社内でも、一部の社内アプリケーション (日本法人における社内の人物検索のアプリケーション、など) では Windows Azure が使用されており、こうしたアプリケーションでは、Windows Azure Active Directory の Access Control Service (ACS) を使った AD FS フェデレーションが採用されています。(社内からつないだ場合には自動的に AD で認証され、Windows Phone などドメイン外からつないだ場合には ID / パスワードの入力が促されます。)
この便利な AD FS フェデレーションについて、下記に、開発者向けに、画面を使用せず、プログラム コードのみから使用する方法について記載しておきます。
追記 : これからはじめられる方は、ここで解説する ACS ではなく、Azure Active Directory (Azure AD) を使用してください。Azure AD と AD (Windows Server) の構成手順は「Azure AD と Active Directory の Federation (および同期) の手順」に記載しました。
概要 (背景)
OAuth など、クレーム ベース認証の多くが Passive Authentication という方式を前提としており、この方式では、ブラウザー上のクッキー (Cookie) などを使った SSO (シングル サイン オン) が前提となっているため、Web ブラウザーや、WebBrowser コントロールなどを使った処理が前提となっています。そして、AD FS / ACS を使った標準的なフェデレーションも、この方式が使用されます。(なお、WebBrowser コントロールを使った制御方法については、まもなく、How-To 系コンテンツ でも紹介する予定です。)
しかし、プログラマーにとっては、Passive Authentication では都合が悪い場合があります。例えば、バックエンドのプログラム (サーバー上で動いているバッチなど) から、プログラム コードを使って認証をおこないたい場合です。この場合、ユーザーにブラウザーを表示して、明示的にログイン処理をおこなってもらうことは不可能です。他にも、ブラウザーを持っていないデバイス環境などから利用する場合も同様です。
実は、AD FS 2.0 を使用したフェデレーションでは、ブラウザーを使用しない Active Authentication という方式が使用できるようになっていて、この方式を使うことでこの問題を克服できます。(なお、この方式を提供しているのは、AD FS など、一部のクレーム ベース認証基盤のみです。)
そこで、今回は、AD FS / ACS 連携を例に、Active 認証をプログラム コードで処理する方法について解説したいと思います。
補足 : 当然ですが、Web Api など、こうした呼び出し (プログラムからの暗示的な呼び出し) が必要なサービスでは、Basic 認証を使うなど、クレーム ベース認証以外の方式を使えば充分です。(わざわざ、プログラムから扱いづらいクレーム ベース認証を使って公開する必要はありません。) しかし、SharePoint Online などのように、アプリケーションと共にサービスが提供され、このアプリケーション全体がクレーム ベース認証で保護されている場合があります。ここで紹介する方法は、こうしたケースで使用することを想定しています。
(なお、SharePoint Online と連携するサンプルについては、次回、解説します。)
事前設定 – AD FS / ACS のセットアップ
まず、あらかじめ、AD FS 2.0 のセットアップ (インストール / 構成) と、Windows Azure Active Directory の ACS と AD FS 間のフェデレーション構成をおこないます。
ここでは、これらの基本的なセットアップ方法の説明は省略しますが、「Windows Azure ACS を使用して AD FS とのフェデレーションを構成する」に ADFS / ACS のフェデレーションの構成手順を記載していますので、参照にしてください。(陥りやすいポイントなども、執筆者の中原さんが、Note として記載してくれています。)
また、AD FS 2.0 そのもののインストール方法や注意点などについては、エバンジェリスト 安納の公開しているブログやコンテンツが参考になると思います。
事前設定 – エンドポイントの有効化
基本的なインストールと設定が完了したら、つぎに、Active Authentication (Active 認証) をおこなうために、AD FS 上で、Active 認証で使用するエンドポイントを有効にします。
AD FS 2.0 のサーバーにログインし、[AD FS 2.0 の管理] 画面を開いて、下図の通り、以降で使用する <AD FS 2.0 サーバー>/adfs/services/trust/13/windowsmixed のエンドポイントを有効 (Enabled) に設定します。
設定が完了したら、[AD FS 2.0 Windows サービス] を再起動します。
プログラミング
今回のサンプル コードでは、コンソール アプリケーションから接続をおこない、AD FS のフェデレーション認証を処理して、Windows Azure 上の Web アプリケーションのトップ ページ (default.aspx など) の内容を取得してみましょう。
この際、セキュリティーに関する SOAP エンベロープの処理 (WS-Trust の処理) など、面倒な処理を最初からプログラミングする必要はありません。WS-Trust、WS-Federation などを使ったクレーム ベース認証を処理する場合、Windows Identity Foundation (WIF) のライブラリー (Microsoft.IdentityModel.dll) が使えます。
補足 : Silverlight 用の WIF のオープン ソースも提供されており、Windows Phone アプリケーションなどでも使用できます。このサンプル コードは、エバンジェリスト 安納のブログ で紹介されています。
まず、Visual Studio を起動し、コンソール アプリケーションのプロジェクトを新規作成します。
作成したコンソール アプリケーションの対象フレームワークを [.NET Framework 4 Client Profile] から [.NET Framework 4] に変更して (下図)、プロジェクトに、System.Web.dll、System.ServiceModel.dll、System.Runtime.Serialization.dll、System.IdentityModel.dll、%programfiles%\Reference Assemblies\Microsoft\Windows Identity Foundation\v3.5\Microsoft.IdentityModel.dll のアセンブリ参照を追加します。(System.Web.dll は、このあと使用する HttpUtility クラスのために参照しています。)
つぎに、AD FS サーバーに接続して、トークン (Assertion) を取得するコードを作成してみましょう。Program.cs に、下記 (太字) の通りコードを記述します。
下記のコードでは WCF を使用していますが、WS-Trust 用のバインド構成など複雑な処理は、WSTrustChannel、WindowsWSTrustBinding など WIF (Windows Identity Foundation) が提供するクラスを使用しています。また、AD FS サーバーに渡す SOAP のエンベロープ (WCF の Message) についても、提供されている RequestSecurityToken クラスを使うことで (内部で) 作成してくれます。
なお、下記では、Bearer キーのトークンを要求していますが、暗号化された Symmetric キーのトークンを扱う方法については、さいごに補足したいと思います。
. . .using System.Net;using System.ServiceModel;using Microsoft.IdentityModel.Protocols.WSTrust;using Microsoft.IdentityModel.Protocols.WSTrust.Bindings;. . .static void Main(string[] args){ // // get SAML token from AD FS // WSTrustChannelFactory idpFactory = new WSTrustChannelFactory( new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress(new Uri(@"https://adfsserver.testdomain.com/adfs/services/trust/13/windowsmixed"), EndpointIdentity.CreateSpnIdentity(@"host/kkdeveva01.testdomain.com"))); idpFactory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13; idpFactory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials; RequestSecurityToken reqToken1 = new RequestSecurityToken( WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Bearer); reqToken1.AppliesTo = new EndpointAddress(@"https://adfstest.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric"); reqToken1.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11; WSTrustChannel idpProxy = (WSTrustChannel) idpFactory.CreateChannel(); System.IdentityModel.Tokens.SecurityToken issuedToken1 = idpProxy.Issue(reqToken1); idpFactory.Close(); // we'll describe the following programs below . . .}. . .
補足 : ここでは、フェデレーション サーバー プロキシ を使わず (フェデレーション サーバーのみで) AD FS のみを構成し、ドメイン内のクライアントから Windows 統合認証を使って接続する場合を想定しています。(外部からプロキシーに要求する場合は、UserName の Credential を要求することになるでしょう。)
このため、上記のコードの SPN Identity は、WCF を使った SSPI による認証で必要です。
補足 : デバッグに際し、AD FS サーバー側で発生したエラーは、イベント ビューアー (eventvwr) で確認できます。
つぎに、上記で受け取った AD FS のトークン (issuedToken1) を使って、ACS にトークンを要求します。Program.cs に、下記 (太字) の通りコードを追加します。
前述と似た処理ですが、ここでは、IssuedTokenWSTrustBinding を使用している点に注意してください。IssuedTokenWSTrustBinding では、BearerKey も処理できるように、下記の通り KeyType プロパティを設定します。
また、下記の通り、idpFactory.Credentials.SupportInteractive = false とすることで、Windows CardSpace (旧バージョンのクレーム ベース処理) の UI を抑制しています。(UI を表示せずに、プログラム コードでトークンを処理しています。)
. . .static void Main(string[] args){ // // get SAML token from AD FS // . . . // // get SAML token from ACS // IssuedTokenWSTrustBinding acsBinding = new IssuedTokenWSTrustBinding() { SecurityMode = SecurityMode.TransportWithMessageCredential, KeyType = System.IdentityModel.Tokens.SecurityKeyType.BearerKey, EnableRsaProofKeys = true, TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13 }; WSTrustChannelFactory acsFactory = new WSTrustChannelFactory( acsBinding, new EndpointAddress(new Uri(@"https://adfstest.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric"))); acsFactory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13; acsFactory.Credentials.SupportInteractive = false; RequestSecurityToken reqToken2 = new RequestSecurityToken( WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Bearer); reqToken2.AppliesTo = new EndpointAddress(@"https://adfstestwebapp.cloudapp.net/"); reqToken2.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11; acsFactory.ConfigureChannelFactory(); WSTrustChannel acsProxy = (WSTrustChannel)acsFactory.CreateChannelWithIssuedToken(issuedToken1); RequestSecurityTokenResponse securityTokenResponse2; acsProxy.Issue(reqToken2, out securityTokenResponse2); acsFactory.Close(); // we'll describe the following programs below . . .}. . .
補足 : ここでは、有効期限に関する処理 (プログラミング) は省略しますが、発行されるトークンは、既定で 10 分間の有効期限があります。(このため、例えば、AD FS サーバーの時計がインターネット上の時刻と異なっている場合、エラーとなることがあるので注意してください。)
有効期限は、securityTokenResponse2.Lifetime.Expires で取得できます。
以上で、トークンの取得は完了です。
さいごに、ACS から受け取った上記のトークン (securityTokenResponse2) を使って、Windows Azure 上の Web アプリケーション (Relying Party) から認証用のクッキー (下記の FedAuthValue, FedAuth1Value) を取得します。(下記の通り、コードを記述します。)
. . .using System.IO;. . .static void Main(string[] args){ // // get SAML token from AD FS // . . . // // get SAML token from ACS // . . . // // login to RP (and, get FedAuth cookie) // string FedAuthValue = string.Empty; string FedAuth1Value = string.Empty; StringBuilder rstrSb = new StringBuilder(); System.Xml.XmlTextWriter rstrWr = new System.Xml.XmlTextWriter(new StringWriter(rstrSb)); WSTrustFeb2005ResponseSerializer rstrSr = new WSTrustFeb2005ResponseSerializer(); rstrSr.WriteXml(securityTokenResponse2, rstrWr, new WSTrustSerializationContext()); string rstrStr = rstrSb.ToString(); HttpWebRequest webRequest1 = HttpWebRequest.Create("https://adfstestwebapp.cloudapp.net/") as HttpWebRequest; webRequest1.Method = "POST"; webRequest1.ContentType = "application/x-www-form-urlencoded"; webRequest1.CookieContainer = new CookieContainer(); webRequest1.AllowAutoRedirect = false; string dataStr = string.Format("wa=wsignin1.0&wresult={0}&wctx=rm=0&id=test&ru=%252f", System.Web.HttpUtility.UrlEncode(rstrStr)); byte[] dataByte = Encoding.UTF8.GetBytes(dataStr); using (Stream reqStream1 = webRequest1.GetRequestStream()) { reqStream1.Write(dataByte, 0, dataByte.Length); reqStream1.Close(); } using (HttpWebResponse webResponse1 = webRequest1.GetResponse() as HttpWebResponse) { FedAuthValue = webResponse1.Cookies["FedAuth"].Value; FedAuth1Value = webResponse1.Cookies["FedAuth1"].Value; } // we'll describe the following programs below . . .}. . .
なお、Web アプリケーション (RP) 側も特別なプログラミングは不要で、WIF の構成 (上記の「Windows Azure ACS を使用して AD FS とのフェデレーションを構成する」を参照) がサーバー側の処理をすべておこなってくれています。
取得したクッキー (FedAuth, FedAuth1) を使って、Web ページや REST サービス (Web Api) などの呼び出しが可能です。以下では、default.aspx のページの内容を取得しています。
static void Main(string[] args){ // // get SAML token from AD FS // . . . // // get SAML token from ACS // . . . // // login to RP (and, get FedAuth cookie) // . . . // // Call test // string result = string.Empty; CookieContainer cc = new CookieContainer(); cc.Add(new Cookie("FedAuth", FedAuthValue) { Path = "/", Domain = "adfstestwebapp.cloudapp.net" }); cc.Add(new Cookie("FedAuth1", FedAuth1Value) { Path = "/", Domain = "adfstestwebapp.cloudapp.net" }); HttpWebRequest webRequest2 = HttpWebRequest.Create("https://adfstestwebapp.cloudapp.net/Default.aspx") as HttpWebRequest; webRequest2.Method = "GET"; webRequest2.CookieContainer = cc; using (HttpWebResponse webResponse2 = webRequest2.GetResponse() as HttpWebResponse) { using (StreamReader resReader2 = new StreamReader(webResponse2.GetResponseStream())) { result = resReader2.ReadToEnd(); resReader2.Close(); } }}. . .
もちろん、Web アプリケーション側 (RP 側) では、ADFS から渡されるクレーム情報 (ユーザー名、E メールアドレス、などの属性情報) も正しく取得できます。
今回は、証明書利用者アプリケーション (RP, Relying Party) が使用するトークンとして SAML 2.0 を使用していますが、SWT を使って保護している場合も Active 認証によって処理できます。(このサンプル コードについては、[MSDN] Requesting a Token from AC を参照してください。)
また、上記では、認証のステップ (流れ) が理解できるよう、それぞれ処理を分解して記述しましたが、RP (Relying Party) が WCF サービスの場合は、WIF の IssuedTokenWSTrustBinding を使って、こうした処理を単一のバインド構成 (Binding) で記述できます。(このサンプル コードは、「CodePlex : Access Control Service Samples and Documentation」の Acs2FederationSample プロジェクトに入っています。)
次回の投稿では、Office 365 の Microsoft Federation Gateway (MFG) を使って同様のプログラミングをおこなってみましょう。
==========
補足 : Symmetric キーを使った Active Authentication
上記では Bearer キー (暗号化されていない Assertion) を使って Active authentication をおこないましたが、暗号化されたトークン (EncryptedAssertoin) を使う場合について 以下に補足しておきます。(なお、EncryptedAssertion を使わなくても、HTTP のエンベロープ自体は SSL により暗号化されていますので安心してください。)
1. AD FS / ACS 間のトークン暗号化
以下の手順で、AD FS から STS (ACS) に渡すトークンを暗号化しておきます。(AD FS 側の暗号化と、ACS 側の暗号化解除の設定をおこないます。)
まず、証明書を作成します。(今回は、自己署名の証明書を使います。)
Visual Studio コマンドプロンプトを管理者権限で起動し、下記を実行してください。(下記で adfstest.accesscontrol.windows.net には、<ACS の名前空間>.accesscontrol.windows.net を設定してください。また、パスワードの設定と入力を促されるので、適宜設定してください。)
makecert.exe -r -pe -n "CN=adfstest.accesscontrol.windows.net" -sky exchange "adfs_acs_token.cer" -sv "adfs_acs_token.pvk"pvk2pfx -pvk "adfs_acs_token.pvk" -spc "adfs_acs_token.cer" -pfx "adfs_acs_token.pfx" -pi <パスワード>rem -- なんちゃって CA の作成makecert -r -pe -n "CN=My Root Authority" -ss CA -sr CurrentUser -a sha1 -sky signature -cy authority -sv CA.pvk CA.cerrem -- なんちゃって server 証明書の作成makecert -pe -n "CN=adfstest.accesscontrol.windows.net" -a sha1 -sky Exchange -eku 1.3.6.1.5.5.7.3.1 -ic CA.cer -iv CA.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv adfs_acs_token.pvk adfs_acs_token.cerpvk2pfx -pvk adfs_acs_token.pvk -spc adfs_acs_token.cer -pfx adfs_acs_token.pfx -pi <password>
上記の証明書を Windows Azure Active Directory の ACS に設定します。
ACS の管理ポータルを開き、[証明書およびキー] 画面を表示して、[トークン暗号化解除] の [追加] ボタンを押して、上記の .pfx ファイルとパスワードを設定します。
つぎに AD FS 側に証明書を設定します。
AD FS のサーバー上で、[AD FS 2.0 の管理] を開き、[証明書利用者信頼] に設定されている ACS (STS) を選択して、プロパティ画面を開きます。表示される画面で [暗号化] タブを選択して、上記で作成した .cer ファイルを設定します。(念のため、[AD FS 2.0 Windows サービス] を再起動しておきましょう。)
2. ACS / RP 間のトークン暗号化
同様に、今度は、ACS と証明書利用者アプリケーション (RP, Relying Party) の間のトークン暗号化を設定します。
上記同様、Visual Studio コマンドプロンプトを管理者権限で起動し、下記を実行します。(下記で、adfstestwebapp.cloudapp.net には、お使いの RP のドメインを設定してください。)
makecert.exe -r -pe -n "CN=adfstestwebapp.cloudapp.net" -sky exchange "acs_rp_token.cer" -sv "acs_rp_token.pvk"pvk2pfx -pvk "acs_rp_token.pvk" -spc "acs_rp_token.cer" -pfx "acs_rp_token.pfx" -pi <パスワード>rem -- 上記で作成した CA の証明書を使用makecert -pe -n "CN=adfstestwebapp.cloudapp.net" -a sha1 -sky Exchange -eku 1.3.6.1.5.5.7.3.1 -ic CA.cer -iv CA.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv acs_rp_token.pvk acs_rp_token.cerpvk2pfx -pvk acs_rp_token.pvk -spc acs_rp_token.cer -pfx acs_rp_token.pfx -pi <password>
Windows Azure Active Directory の ACS の管理ポータルを開き、[証明書およびキー] 画面を表示して、[トークン暗号化] の [追加] ボタンを押して、上記の .cer ファイルを設定して [保存] ボタンを押します。
ACS 管理ポータルの [証明書利用者アプリケーション] の [暗号化ポリシー] 欄で、[暗号化を必要とする] を選択します。
つぎに、証明書利用者アプリケーション (RP, Relying Party) に上記の証明書 (Private key を持つ証明書) を登録します。
Windows Azure 上のアプリケーション インスタンスの証明書リポジトリ (今回は、ローカル コンピューターの My を使用します) に暗号化解除のための証明書 (秘密キーを含んだ証明書) を登録し、これをアプリケーション (RP) から使用しますが、そのための準備として、まずは、以下の手順で、開発環境 (ローカル環境) の証明書リポジトリ (ローカル コンピューターの My) にこの証明書を登録しておきます。
- [スタート] – [ファイル名を指定して実行] を選択して「mmc」と入力します。(Microsoft 管理コンソールが表示されます。)
- Microsoft 管理コンソールで、[ファイル] – [スナップインの追加と削除] を選択して、[証明書] を選択します。
- この際、ユーザー アカウント (Current User) に対する証明書か、コンピューター アカウント (Local Computer) に対する証明書か聞かれるので、「コンピューター アカウント」を選択します。
- 表示される画面の [個人] – [証明書] に、上記で作成した .pfx ファイル (private key の入った証明書) をインポートします。
ACS を使ったアプリケーションでは、ご存じの通り、証明書利用者アプリケーション (RP, Relying Party) のプロジェクトを Visual Studio で開き、[STS 参照の追加] (%programfiles%\Windows Identity Foundation SDK\v3.5\FedUtil.exe) を実行することで、ウィザード ベースで、クレーム ベース認証の処理を設定できます。このウィザード (FedUtil.exe) で、下記の通り、セキュリティ トークンの暗号化を有効にしておきます。
上図の [証明書の選択] ボタンを押すと、上記でローカル コンピューターに登録した証明書が表示されるので、これを選択して、クレーム ベース認証の構成をおこないます。(.config が変更されます。なお、上級者の方は、Fedutil.exe を使わず、あとから、Web.config の内容を変更しても構いません。)
さいごに、Windows Azure 管理ポータルを開き、対象の Hosted Services の [証明書] に、上記で作成した .pfx ファイルを追加 (アップロード) します。(この際、パスワードを入力します。)
さらに、証明書利用者アプリケーション (RP, Relying Party) のプロジェクトを Visual Studio で開き、ロールのプロパティ ウィンドウを開いて、証明書 (Certificates) を設定します。(下図の通り、Store Location を LocalMachine、Store Name を My としてください。)
以上の設定終了後、念のため、ちゃんと Passive の Federation (通常の Web ブラウザーを使った接続と AD FS 認証) がおこなわれることを確認してみてください。動作は変わりませんが、内部では、暗号化トークン (Encrypted Assertion) が使用されています。
補足 : 当然ですが、上記はトークン暗号化のための設定であり、SSL 暗号化の設定ではありませんので、勘違いしないようにしてください。SSL の設定方法については、「10 行でズバリ ! Windows Azure アクセスコントロール サービス (ACS) を利用する」に記載されています。(ここでは、説明を省略します。)
3. プログラミング
プログラムは、上記とほとんど同じですが、AD FS にトークンを要求する際に、暗号化された Symmetric キーを持つトークンを要求します。
つまり、下記 太字の通り変更するだけで OK です。(なお、この場合でも、ACS に対しては Bearer トークンを要求してください。試してみましたが、この方法では、RP が Bearer トークンしか受け付けないようです。。。)
. . .static void Main(string[] args){ // // get SAML token from AD FS // WSTrustChannelFactory idpFactory = new WSTrustChannelFactory( new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress(new Uri(@"https://adfsserver.testdomain.com/adfs/services/trust/13/windowsmixed"), EndpointIdentity.CreateSpnIdentity(@"host/kkdeveva01.testdomain.com"))); idpFactory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13; idpFactory.Credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials; RequestSecurityToken reqToken1 = new RequestSecurityToken( WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Symmetric); // changed here ! reqToken1.AppliesTo = new EndpointAddress(@"https://adfstest.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric"); reqToken1.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11; WSTrustChannel idpProxy = (WSTrustChannel) idpFactory.CreateChannel(); System.IdentityModel.Tokens.SecurityToken issuedToken1 = idpProxy.Issue(reqToken1); idpFactory.Close(); // // get SAML token from ACS // . . . (same as the above) // // login to RP (and, get FedAuth cookie) // . . . (same as the above) // // Call test // . . . (same as the above)}. . .
なお、呼び出される Web アプリケーション (Relying Party) 側の暗号化解除 (Decryption) の処理は、すべて、上記で設定した WIF の構成がおこなってくれます。 (暗号化解除のための面倒な処理をプログラミングする必要はありません。)
Categories: Uncategorized
4 replies»