はまったりひらめいたり…とか…

Angularや.NETやAzureやその他色々。

AngularでQR/バーコードを使用するInputコントロールを作る

12/1 修正しました。

はじめに

今回のお話は、下記バージョンでお送りします

AngularCLI : 7.0.4

↓みたいなコントロールを作成していきます。

f:id:TakasDev:20181123231755g:plain

f:id:TakasDev:20181123232143g:plain

テキストボックスがあり

フォーカスが当たった際に、ソフトウェアキーボードではなくQRを読み込むカメラが起動し

カメラでQRが読み込めた場合

フォーカスが当たっていたテキストボックスに、QRから読み取った値を投入する。

といった動作です。

QR/バーコード読み込み

以前の記事でQRコードを読み取るために、@zxing/ngx-scanner を使用しました。

今回は、そのライブラリからForkされた、@innotec/ngx-scanner を使用します。

@innotec/ngx-scanner - npm

npm install @innotec/ngx-scanner --save

@zxing/ngx-scannerの@Inputにはformatsが追加されており、CODE39等のバーコードのFormatを指定することで

バーコードのデータも読み込むことができるようになります。

Formatの指定は、@zxing/libraryEnumで管理されている、BarcodeFormat の配列を使用します。

Selectorはzxingのngx-scannerと同様なので、下記のようにFormatを指定する部分のみが変わる感じです

<zxing-scanner #scanner
  [formats]="[BarcodeFormat.QR_CODE, BarcodeFormat.CODE_39]">
</zxing-scanner>

ngx-scannerの使い方は、以前書いた記事を参考にしていただければと思います。

AngularでQRする - はまったりひらめいたり…とか…

Angular Material BottomSheet

画面下からにゅっと飛び出てくるコントロールを作るために

AngularMaterialのBottomSheetコンポーネントを使用しました。

Angular Material

準備

まずは、Materialを使用するために、お決まりの

ng add @angular/materialを行っておきます。

@NgModuleでBottomSheeetのモジュールMatBottomSheetModuleをインポートしておきます。

コンポーネントからの使用

constructorでMatBottomSheetのDIを行うことで、BottomSheetの処理が使用可能になります。

コンポーネントから、BottomSheetのOpen() を実行すればBottomSheetが表示されます。

その際、BottomSheet内に表示するComponentを指定することが可能です。

≪MatBottomSheet≫.open(SheetBodyComponent);

この時BottomSheetに表示されるComponentは、表示されるタイミングでインスタンス化されるようなので

LazyLoadするComponentの時同様、NgModuleのEntryComponentに加えてあげる必要があるようです。

@NgModule({
...
  entryComponents: [
    SheetBodyComponent
  ],
...
})
export class AppModule { }

サービスの注入

QR/バーコードが読み込まれたタイミングで、親コンポーネントがその結果を引っ掛けたいです

ただ、BottomSheet内のComponentは、EntryComponentなので、@Outputあたりで引っ掛けるのも難しそうです。

なのでDIするClassを作成し、その中のSubjectなプロパティを介して

BottomSheet内Componentと、親Componentでデータのやり取りを行う方法をとろうと思います。

コンポーネント

// BottomSheetをOpen
const res = ≪MatBottomSheet≫.open(SheetBodyComponent);

≪DI Class≫.≪Subjectプロパティ≫.subscribe(x => {
  // QR/バーコードがScan出来た場合
  // InputElementに対して取得したQR結果を突っ込む
  // ElementRefを使用しInputコントロールを取得する
  const con = <HTMLInputElement>≪ElementRef≫.nativeElement.querySelector('input');
  con.value = x;
  // BottomSheetを閉じる
  res.dismiss();
});

BottomSheet内コンポーネント

handleQrCodeResult(resultString: string) {
  // QRが読み込めた時の処理。サービスのSubjectプロパティに値を流す
  ≪DI Class≫.scanSuccess.next(resultString);
}

スクリプト内で特に指定しない限り、BottomSheetはEscキーなり、BottomSheet外をClickするなりしないと閉じないので

値が読み込めた段階で、bottomsheetのdismiss()を使用して用がすんだら閉じてあげるのが良いかと思います。

bottomsheetのafterDismissed().subscribe()で、BottomSheetが閉じた時を引っ掛けれるので

BottomSheet閉じた際に何か処理をしたい場合は、そいつを使うと楽にいろいろできそうです。

これで、親ComponentとBottomSheetのComponentでデータのやり取りが可能になりました。

結果

冒頭のGifの通り、QR/バーコードを使用したInputコントロールが作成できました。

おわりに

ソフトウェアキーボードみたいな、フォーカスあてると下からニュッと入力インターフェースが出てくるコントロールを作りたいという思いでBottomSheetを使用しました。

今回はQR/バーコードの読み取りで使用しましたが

Canvasあたりを使用すれば、手書きの入力コントロールも、OSのインターフェースっぽく表現できるかもしれませんね。

今回作成したものは、下記リポジトリで管理しています。

サンプルで作ったもののごった煮ですがご容赦ください。

github.com

バーコードとQRの生成は下記のサイトを使用しました。

バーコード

barcode.tec-it.com

QR

m.qrqrq.com

Azure DevOpsとBlob StorageでClickOnceアプリケーションのCI/CDできるか「雑に」試してみた

はじめに

れがしぃなWindowsFormsなプロジェクトをAzure DevOps(ADO)でCI/CDできるか「雑に」試してみました。

exeをどこかに吐き出すだけでは面白くないので

Azure Blob Storage上にClickOnceアプリケーションをデリバリして

Web Apps上のリンクからそのアプリケーションを使用する。

みたいな形で構成していこうと思います。

「できるかな?」程度なので、超雑な構成になっています。

証明書周りやCORS周りなんかは、もうちょっと検証が必要と思います。。。

最終的に↓な感じで動きます。

f:id:TakasDev:20181118193605g:plain

Windows Formsプロジェクト

まずはWindowsFormsプロジェクトの作成です。

といっても、アプリケーション自体はそこまで重要ではないので

WindowsFormsの画面を表示させるだけの機能のものです。

アプリケーションの発行する際にClickeOnceの署名等も行うよう設定しておきます。証明書はVisualStudioで作成されるテスト証明書をそのまま使用します。

f:id:TakasDev:20181118182610p:plain

ADO CI/CDパイプライン

VisualStudioBuildタスク

ADOパイプラインのVisualStudioBuildタスクはデフォルトで、publishしてくれないので、タスクの内容を少しいじります

MSBuild:Arguments/target:publish を指定するだけです。

f:id:TakasDev:20181118182713p:plain

PowerShellタスク

WinFormsのClickOnceで証明書を使用しているため、Buildを行う際にはマシンの証明書ストアに証明書がインストールされている必要があります。

PowerShellタスクを使用して、ビルドマシンに証明書をインストールしてあげます。

証明書ファイルはめっちゃ雑ですが

ソリューションに加えられたpfxファイルをADOにあげちゃってます

f:id:TakasDev:20181118182837p:plain

$pfxpath = 'pfxファイル'
$password = '証明書パスワード'

Add-Type -AssemblyName System.Security
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($pfxpath, $password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]"PersistKeySet")
$store = new-object system.security.cryptography.X509Certificates.X509Store -argumentlist "MY", CurrentUser
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]"ReadWrite")
$store.Add($cert)
$store.Close()

f:id:TakasDev:20181118182943p:plain

Azure File Copyタスク

ClickOnceアプリケーションは bin の中に生成されるので

binディレクトリの中のファイルをFile CopyタスクでBlobストレージにアップロードします。

f:id:TakasDev:20181118191122p:plain

基本的にAzureのBlob Storageとリンクされます。なので迷わず設定できます。

結果

f:id:TakasDev:20181118191451p:plain

指定したコンテナに.application他生成されたファイルがコピーされました。

Blob Storage他の雑な設定変更

ここからかなり雑です。

アセンブリの設定変更

オレオレ以前な証明書を使用しているので、*.application にアクセスしてもファイルの起動が行なえません。

f:id:TakasDev:20181118192258p:plain

Let'sやらOpenSSLを使用してあげれば回避できるとは思うのですが

今回は、コンピューター\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\Security\TrustManager\PromptingLevel の設定をすべてenabledに変更して回避しました。

BlobStorageのアクセスポリシー変更

当初、SASトークン付きのURLでapplicationファイルにアクセスしていたのですが

アプリケーションのインストールを行う際、当然 .manifest などの他のファイルもBlobStorage経由で取得しようとします。

しかし、アプリケーションのインストール時は、インストーラSASトークン付きのURLに対してアクセスしてくれないため、404が発生し、インストール時にエラーとなってしまいます。

BlobStorageでCORSを設定してみたのですが、そもそもローカルにインストールされたインストーラからのアクセスなので、CORSも効かない…

ので、アクセスポリシーをユッルユルに設定しアクセスできるようにしました。

f:id:TakasDev:20181118192830p:plain

雑に設定した結果

.application へのLinkを貼っただけのHtmlをアップし動作させてみました。

結果は記事の冒頭に貼った通りの結果でClickOnceのおなじみの動きとなっています。

おわりに

BlobStorageにアップしたClickOnceアプリケーションは使用できそうです。

ただ、さすがにAnonymousで制限なくアクセス可能。という状態を避けたい場合はもうすこし考慮が必要かもしれません。

アプリケーションへのエントリがWebからのみ。ということであれば

Web画面のCI/CDパイプラインでアプリケーションを混入した状態で、WebAppsにデプロイしちゃったほうが良いかもしれないですね。

Azure DevOpsでAngularのJestテストのCIをまわせるか試してみた

はじめに

Angularは下記Verisonでお届けします。

  • AngularCli:7.0.3

先日の、bitbank LT NightでみたJestがとても良い感じで使ってみたくなったので

現在使用しているCI環境のAzure DevOps(以降ADOと呼びます)で使用できるか確認してみました。

jestjs.io

Azure DevOps

お仕事で使用していますが、Publicなプロジェクトでも使用できます。

Publicなプロジェクトの場合(厳密にはOSSプロジェクトとのことですが)、ビルド時間を無制限に回せるようです。

Azure DevOps のご紹介 – Cloud and Server Product Japan Blog

WebからWindowsアプリ、Andorid/iOSもビルド可能となかなか最強味が強い環境です。

OneDriveみたいに、無制限→制限!のような未来を辿らなければいいと願っています。

Angularの下準備

まずはAngularでJestのテストができるようにします。

下記を参考にしました。

izifortune.com

ひとまず、ng new したプレーンな環境から作成しました。

上記の記事に記載されている通りの変更を行います。

  • パッケージのインストール
  • jestテストするためのスクリプトをpackage.jsonに追加
  • jestの設定ファイルのjest.tssrc ディレクトリに配置
  • tsconfig.spec.jsonの変更

あっさりとJestでテストが可能なところまで持っていくことができました。

f:id:TakasDev:20181111192325p:plain

結果レポートの出力

前の記事の内容の通り、ADOはjUnitXMLを食わせばレポート出力してくれるので

jestからjUnitのレポートを出力できるようにします。

パッケージのインストール

jUnit出力に使用するパッケージをインストールします。

npm install --save-dev jest-junit

レポート出力の設定

Jestコマンドでレポート出力されるよう、package.jsonの設定を変更していきます。

  "jest": {
...
    "reporters": [
      "default",
      "jest-junit"
    ]
  }

defaultが先程行ったコマンドラインで表示されるテスト

jest-junitjUnitXML形式で出力されるテストの設定です。

今回は、jest-junitのオプションに特に指定をしないので

rootディレクトリに「junit.xml」という名前で結果ファイルが出力されます。

テストコマンドも少し変更します。

今回の変更でテストレポートが複数パターンになったので

テスト内容によってどっちのレポートを使用するか指定しておきます。

package.jsonスクリプトを下記のように変更しました。

  "scripts": {
...
    "test": "jest --reporters=default",
    "test:ci": "jest --reporters=jest-junit",
...
  }

スクリプトコマンドの通り、npm run test:ciXMLが出力されます。

CIの構築

今回はGitHubリポジトリから、ソースを引っ張ってきてADOでCIします。

せっかくなので、Public環境のADOを使用しようと思います。

ADOの設定

GitHubリポジトリからソースを引っ張ってくるパイプラインを作ります。

f:id:TakasDev:20181111194540p:plain

f:id:TakasDev:20181111194659p:plain

NewPipelineでGitHubを選択するだけ。簡単ですね。

テンプレートはどうせあとからいじるので、Blankなものを選択します

パイプラインを作成したら、ソースのリポジトリのルートディレクトリに

パイプラインの設定ファイルazure-pipelines.ymlが追加されています。

パイプラインをYamlで作成

パイプラインができたら、Buildの設定を作っていきます。

ADOのCIは、デフォルトではルートディレクトリにある、azure-pipelines.yml の設定を参照し、CIのパイプラインが実行されます。

今回は、下記の感じで構成しました。

ルートディレクトリ配下にAngularのプロジェクトファイルがあるのでちと変則的ですが…

resources:
- repo: self
queue:
  name: Hosted VS2017
  demands: npm

npmインストール
steps:
- task: Npm@1
  displayName: 'npm install'
  inputs:
    workingDir: AngularWithJest

    verbose: false

npmテスト実行。CI用のテストを実行する。
- task: Npm@1
  displayName: 'npm run test'
  inputs:
    command: custom

    workingDir: AngularWithJest

    verbose: false

    customCommand: 'run test:ci'

出力されたXMLファイルをテスト結果として取得する
- task: PublishTestResults@2
  displayName: 'Publish Test Results **/junit.xml'
  inputs:
    testResultsFiles: '**/junit.xml'

  condition: always()

buildする。
- task: Npm@1
  displayName: 'npm build'
  inputs:
    command: custom

    workingDir: AngularWithJest

    verbose: false

    customCommand: 'run prod-build'

ADOのyamlについては、下記サイトが参考になります。

YAML schema - Azure Pipelines | Microsoft Docs

結果

あえて失敗するテストを混入した状態でCIを回しました。

下記の通りきちんとエラーの内容が出力されています。

f:id:TakasDev:20181111200640p:plain

エラーを修正し、再度CIを回すと、きちんと反映されていることが確認できます

f:id:TakasDev:20181111210118p:plain

最後に

そもそもJest使用できるかな?程度のものなので、まだまだ検証することは多いかなと思います。

Jestは全然触っていないので、これからいろいろ覚えたい感じです。

さて、今回作成したソースと環境は下記になります。

Publicな環境でAzure DevOpsプロジェクト作成したのでテスト結果も見る事が可能です。

GitHub:AngularXStudy

Azure DevOps: angularxstudy-ci

(僕の失敗の軌跡も見ることができるので少し恥ずいですが…)

AngularでQRする

はじめに

この記事は、下記のVersionでお送りします。

  • Angular CLI : 7.0.3

どんな風に動作する?

こんな感じです。ちょっと見えづらいですが

一番下部で数字をカウントしているのがQRコードの読み取り結果です。

QRは2秒毎に0からカウントアップしていき、秒数をQRコードに変換しています。

QRコードの読み取りは早い方ではないでしょうか?

f:id:TakasDev:20181101070256g:plain

AngularでQRコードを読む

使用するライブラリ

QRコードを読むライブラリとしては、ネイティブではZxingが有名だと思います。

Angular用のZxingライブラリのngx-scannerが開発されいますので

今回はそれを使用しようと思います。

github.com

注意

今、iOS12でQRを読み込んでくれないバグが存在するようです。

が、上のGifの通り動作していますね。

Angular6 + ngx-scannerの食い合わせが悪いのかもしれません。

(今回、Angularはv7を使いました)

次のリリースで解決するとアナウンスはされていますが、使用する際は注意が必要です。

IOS12 iphone/ipad · Issue #140 · zxing-js/ngx-scanner · GitHub

ngx-scannerの事始め

QRコードの読み取り機能自体は、非常に簡単に使用することができます。

npm i @zxing/ngx-scanner --saveして

Angularでは恒例の、ngModuleでインストールしたライブラリを読み込んでやってから

Htmlテンプレートで<zxing-scanner></zxing-scanner>だけで使用できます。

ただし、Webカメラを使用する必要があるため

それを使用できるようにするまでで、ひと手間必要です。

バイスで使用できるカメラを取得する

zxing-scanner コンポーネントで使用できるカメラを探してくれます。

結果は、コンポーネントcamerasFound ファンクションに

Obserbableで返却されます。

<zxingcomponent>.camerasFound.subscrive( devices => { hogehoge } )

引っ掛けて使用できるカメラデバイスを把握し

使用するカメラを選択する必要があります。

使用するカメラをコンポーネントdevice プロパティに食わせて

使用できる状態にする必要があります。

簡単に書くと下記な感じでしょうか?

    <zxingcomponent>.camerasFound.subscribe((devices: MediaDeviceInfo[]) => {
        <zxingcomponent>.device = <zxingcomponent>.getDeviceById(devices["index?"].deviceId);
    });

ただ、カメラデバイスを見つけた時のObservableのみでdeviceを設定すると

好きなカメラに変更できないので

<zxingcomponent>.device に食わせる値は変数にして

取得した devices を保持して変更できるようにしておいたほうが良いです。

プロパティに使用するカメラの情報を食わせると

カメラを使用してQRを読み込んでくれるようになります。簡単ですね。

読み取り結果を取得する

Scanした結果は、Zxingコンポーネントの 'scanSuccess' ファンクションに

Observableで返却されます。

<zxingcomponent>.scanSuccess().subscribe(result: string => { })

結果を引っ掛けるだけでOKです。

camerasFoundscanSuccess もEventEmitterで結果が返却されているようなので

<zxing-scanner (camerasFound)="hogehoge()" (scanSuccess)="fugafuga()" >...

としてもいいと思います。これも非常に簡単ですね。

AngularでQRコードを生成する

使用するライブラリ

ngx-scannerで紹介されていた ngx-kjua を使用します。

github.com

ngx-kjuaことはじめ

npm install ngx-kjua --save して、同様にngModuleでライブラリを読み込んでから

Htmlテンプレートで<ngx-kjua></ngx-kjua> で使用できます。

カメラ等のデバイスを使用しないため、特に前段階の準備をすることなく使用できます。

QRコードにしたい文字列かimageをコンポーネントのプロパティに下の感じで指定するだけで

QRコードが生成されます。超楽です。

<ngx-kjua [text]="'qrにしたい文字列'"></ngx-kjua>

さいごに

QRコードを用いたアプリケーションを比較的容易に作成することができます。

いろいろと利用できる範囲も広いですし、楽しい使い方もできると思います。

今回作成したWebApplicationは、下記レポジトリで管理してます。

github.com

Angularの勉強で使用したソースのごった煮ですが、ご容赦ください。

VSTSでAngularのユニットテスト

はじめに

今回の記事の構成は下記のとおりです。

  • AngularCLI : 7.0.3
  • Angular : 7.0.1

Azure DevOpsの略し方が未だにつかめていないので

VSTSの名称でお送りいたします。(ADops…?)

今回のゴール

AngularのUnitTestをVSTSで実施し

結果をVSTSのテストレポートで確認するところまでを目指します。

Angularのプロジェクトの作成からテストコードの作成までは割愛します。

ただ、ネット上に転がっている文献では

PhamtomJSを使用しているものが多いのですが

AzureDevOps(VSTS)でHeadlessChromeが使用できるようになっていることもあり

CIテストに必要な工程はだいぶ減っている印象です

github.com

VSTSのReporter出力の準備

VSTSのレポート出力用に、JUnitReporterをインストールします。

また、HeadlessChromeでテストを実行するので、Pupetterもインストールします。

npm i karma-junit-reporter --save-dev

npm i puppeteer --save-dev

karmaでHeadlessChromeを使用する設定を追加していきます。

  • karma.conf.js
process.env.CHROME_BIN = require('puppeteer').executablePath();
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('karma-junit-reporter'), // 追加
      require('@angular-devkit/build-angular/plugins/karma')
    ],
browsers: ['Chrome', 'ChromeHeadless'],  //ChromeHeadlessを追加

karmaのテストレポートでjunitを使用するよう設定追加します。

  • karma.conf.js
    reporters: ['progress', 'kjhtml', 'junit'], // 'jUnitを追加'
    junitReporter: {
      // 出力ディレクトリ
      outputDir: require('path').join(__dirname, '../reports'),
      // 出力ファイル名
      outputFile: 'test-results.xml',
      suite: '',
      useBrowserName: false
    },

Angularのテスト\スクリプト作成

VSTSのCIで実行するテストスクリプトを実装します。

CI環境下で実行するため、HeadlessChromeで一回のみテストを実行するコマンドです。

"citest": "ng test --watch=false --no-progress --browsers=ChromeHeadless",

VSTSのCIパイプラインを構築

VSTSでAngularのテストを行うよう、パイプラインを構築していきます。

1.Angular-cliをインストール

ng コマンドを使用するために@angular/cliをインストールしておきます。

f:id:TakasDev:20181027183006p:plain

2.npm install を実行

f:id:TakasDev:20181027183455p:plain

3.組んだCI用のテストを実行する

f:id:TakasDev:20181027185923p:plain

4.テストが失敗していた場合はレポートを出力する

f:id:TakasDev:20181027192204p:plain

5.テストが成功していた場合はビルドする

f:id:TakasDev:20181027192347p:plain

テストで失敗した場合

f:id:TakasDev:20181027232705p:plain

AngularのTypeScript側で失敗したエラーが

VSTSのレポートから確認できるようになりました。

最後に

少し前まではHeadlessChromeが使えなかったので

PhamtomJSをインストールしたり、設定を追加していたりしたのですが

だいぶ楽にCIの自動テストの構成を作ることができるようになりました。

ただ、npm installをしている関係で、一回のサイクルに5分位かかってしまうので

ビルド時間に制限のあるPrivateリポジトリでのCIについては

乱発しないように注意が必要かもしれません。

Azure WebAppsのHybridConnectionでドハマりしたとき試したこと

Azure WebAppsのHybridConnectionとは、Azure上のVPNなどの閉域網を構成しなくても

社内閉域網サーバー内のデータにアクセスできるツールです。

エンプラ系の課題にリーチしそうですね。

こと、Cloud移行したいんだけど一気には無理・・・なんて要求に対応しやすいです。

WepAppsとオンプレサーバーがつながらない

HybridConnectionはハイブリッド接続マネージャーという

クライアントソフトウェアを介して通信が行われるのですが

基本的にはインストールして、接続するエンドポイントを指定するだけの簡単なものです。

詳細は 過去記事をどうぞ。

しかし、ある環境で試したところ、接続できずに四苦八苦しました。

そのときに試したり確認した色々なことを書いていこうと思います。

0.まずはOSの確認を

HybridConnectionはWebSocketを使用して通信を行っているため

WindowsServerであれば2012以降からしか対応していません。

Hybrid Connection Manager の使用

1.接続設定の確認

HybridConncetionの設定の際に、PCの名称を指定するフィールドがあります。

ここの部分で名称を間違えたり、IPアドレスを指定したりすると繋がりません。

正しい設定になっているかどうか確認します。

2.ファイアウォールの確認

HybridConnectionは送信ポート443を使用して通信します。

ハイブリッド接続マネージャでエンドポイントを設定する際は

受信・送信ともにポート443を開放していないと設定できないですが

設定後は、送信ポートだけの開放でも問題なく動作するようです。

OSのファイアウォールで送信ポート443がブロックされているようであれば

開放してあげましょう。

※もちろん443を潰すということはセキュリティ的に重要なPCの可能性が高いので事前確認は忘れずに!

3.サービスが可動しているか確認

前述の通り、HybridConnectionはハイブリッド接続マネージャを介して通信が行われるので

常駐プロセスが立っているはずです。これが停止されていないか確認します。

4.インターネット接続の確認

それでもつながらない場合、そもそもインターネットにつながっている状態か確認します。

状況により下記の通り対応が分岐されます。

4.1 つながらない

ルーターの設定でブロックされている可能性があるので、ルーターの設定を確認します。

4.2 つながる

Proxyサーバーを介して通信が行われている可能性があるので確認します。

4.2.1 Proxy設定を確認

インターネットオプションから、Proxyを介した接続設定となっているか確認を行います。

4.2.2 ハイブリッド接続の設定を変更

Proxyを介して通信を行う設定となっていた場合

ハイブリッド接続マネージャーも、Proxyを介して通信をするよう変更します。

ハイブリッド接続マネージャーの実行ファイルと、同じディレクトリにある

Microsoft.HybridConnectionManager.Listener.exe.config ファイルの中身を変更します。

設定に下記内容を付け加えます。

<system.net>
 <defaultProxy>
  <proxy usesystemdefault="true" proxyaddress="http://hogehoge.proxyserver:1111" />
 </defaultProxy>
</system.net>

proxyaddress には先程インターネットオプションで確認したProxy設定を記述します。

自分はひとまずこれで接続することができました。

最後に

HybridConnectionは、大雑把に言ってしまえばSSLでデータをやり取りしているだけなので

ハイブリッド接続マネージャーを入れたサーバーで、インターネットにつながるのであれば

netstat とか Test-NetConnection を使用して

通常のネットブラウズで使用されている経路やポートを抑えるのが、解決への早道となりそうです。

AngularとAzureAD認証でログイン機構を簡単に実現したい

最初に

今回使用した環境は下記の通りです。

  • @angular/cli : 6.0.8
  • @angular : 6.0.7

AzureAD認証を支援するJSライブラリ

AzureActiveDirectory認証を支援するJSライブラリとして

MicrosoftからADALというJSライブラリが提供されています。

github.com

マルチテナント型のAzureADB2CはMSALと呼ばれるライブラリを使用するようです。

github.com

ADALのAngularラッパーを取得

Angular使いなので、Angularでadal.jsを使おうと思います。

adal.js自体はnpmでパッケージ提供されていないようです。。。

Angularで使用できるラッパーは提供されているようなのでそいつを使用していきます。

npm install adal-angular4 --save

Angular4と書かれていますが6も対応されています。

Angular6対応版もありますが、Deprecateして4に吸収されているようです。

github.com

(名前、ngx~みたいな形のほうがわかりやすいですよね…)

ServiceをImportしてProvide

まずはInjection宣言されている、AdalSeviceを app.module.ts でProvideします。

import { AdalService } from 'adal-angular4';

・・・

providers: [
    AdalService
],

ADの情報を設定

AdalService.init() に使用するADの情報を食わせる必要があります。

Sampleで指定されているのではTenantとClientIDです。

TenantはADで使用されているドメイン

ClientIDはADに登録されたアプリケーションのApplicationIDを指定します。

handleWindowCallbackでログイン状態の収集

先程ProvideしたAdalServiceを介して認証情報のやり取りを行います。

サービス内の handleWindowCallback() を使用し

サインインされているか~ですとか、Tokenの情報~ですとか

そういった情報が収集されているようです。

ログインされているかの情報は

this._adalService.userInfo.authenticated で確認できるので

ログインされているかを確認し

ログインされていないようであればログインするようにしてみます。

  constructor(
    private _adalService: AdalService,
  ) { }

・・・

ngOnInit() {
    this._adalService.handleWindowCallback();
    if (!this._adalService.userInfo.authenticated) {
        this._adalService.login();
    }
}

このようにしておくと、Componentの初期化と同時に

AD未ログイン状態だった場合は

AzureActiveDirectoryの認証画面にリダイレクトされます。

AdalGuardでComponentの遷移Guard

AdalGuardは、Angularの CanActivate

上記の userInfo.authenticated を使用して

AD未ログインユーザーのRoutingの制限を行うSampleという認識です。

adal-angular4/adal.guard.ts at master · benbaran/adal-angular4 · GitHub

認証されていないユーザーへの移動制限をかけたい場合は

routerの設定のときにAdalGuardを指定するだけでOKといった塩梅です。

ここで認証されていない場合は強制的にリダイレクトかけたりなんだりしたいと思うので

基本的にAdalGuardをそのまま使用することはないかなぁ?と思っています。

今回はLoginComponentからDashboardComponentへの遷移の設定を作ってみます。

const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'dashboard', component: DashBoardComponent, canActivate: [AdalGuard] },
  { path: '', component: LoginComponent },
];

今回はAdalGuardをそのまま使用します。

認証がすでに済んでいるものはURL指定で直接遷移できていますが

認証が済んでいないほうはRouterで遷移ができずに

何も表示されていない状態になっています。

f:id:TakasDev:20180630122308g:plain

AD認証のAuthがかかったASP.net WebAPIへのアクセス

adal-angular4が提供する AdalInterceptor

AngularのHTTP_INTERCEPTORを使用して、ヘッダに認証情報を付与します。

adal-angular4/adal.interceptor.ts at master · benbaran/adal-angular4 · GitHub

なので、app.module.ts でInterceptorのInjectionを行えばいい感じです。

providers: [
    AdalService,
    {
        provide: HTTP_INTERCEPTORS,
        useClass: AdalInterceptor,
        multi: true
    }
],

WebAPIを作る

WebAPIはASP.net CoreでAD認証付きのAPIがテンプレートから作れるので

それでサクッと作ってしまいます。

f:id:TakasDev:20180630122458j:plain

F5実行して動作を見てみます。

アクセスするAPIはデフォルトで存在する /api/values のGetにアクセスしてみます。

まずは、RestletClientから、Token情報を付与しない状態でアクセスしてみます。

f:id:TakasDev:20180630122651p:plain

401エラーが返却されました。認証は問題なく動作しているようです。

AdalInterceptorを通してからアクセスした場合を見てみます。

f:id:TakasDev:20180630122744j:plain

横着してConsole出力で済ませています。

f:id:TakasDev:20180630123336p:plain

Networkからも、HeaderのAuthorizationにTokenが使用されているのが確認できます。

先程失敗したRestletClientで、使用されたTokenを使ってみます。

f:id:TakasDev:20180630123527p:plain

通りました。正しいTokenのようです。

まとめ

JSでのActiveDirectory認証はADALを使用します。

今回はAngularを使用しましたがVue用等

各Frameworkのものも用意されているようです。

ログイン画面やアカウント管理は非常に重要で気も使う部分です。

簡易な要望でADを使用している人や会社が対象であれば

AD認証で認証ロジックを丸投げしてしまうのもありですよね。