7月 232014
 
  • 調べた分だけ。
  • 割とわかりやすかった:Overview of Custom Storage Providers for ASP.NET Identity | The ASP.NET Site
  • 「ASP.NET Webアプリケーション」テンプレートの認証「個人ユーザーアカウント」で作成されたコードを眺めれば何となく分かる。
  • Microsoft.AspNet.Identity.EntityFrameworkとかはEFのCodeFirstでテーブル初期化とかDB読み書きとかやってくれるやつだけど、CodeFirstが嫌でIUserStore自作するなら不要な感じ。
  • UserManagerがASP.NET Identityの中心的存在の予感。
    • OWIN startup classの中でCreatePerOwinContext()にて初期化用Funcを設定する。

PasswordHasherの入れ替え


public class ApplicationUserManager : UserManager<User>
{
    public ApplicationUserManager(IUserStore<User> store) : base(store) { }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(new UserStore(context.Get<HogeDbContext>()));
        manager.PasswordHasher = new HogePasswordHasher();
        return manager;
    }
}

public class HogePasswordHasher : IPasswordHasher
{
    public string HashPassword(string password)
    {
        // 塩を振ったりストレッチングしたりしよう
        throw new NotImplementedException();
    }

    public PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
    {
        if (hashedPassword == HashPassword(providedPassword))
            return PasswordVerificationResult.Success;
        else
            return PasswordVerificationResult.Failed;
    }
}

ちなみに、ASP.NET vNext のデフォルトっぽいPasswordHasherは以下の様な実装。

  1. Rfc2898DeriveBytesでSaltサイズのみ指定(128bitでRNGCryptoServiceProviderによって生成されるランダムSalt)にしてパスワードハッシュ生成(1000回ストレッチング)
  2. Salt + パスワードハッシュな文字列を返す(DBとかに保存する文字列になる)

検証時は

  1. DB保存的文字列からSaltとパスワードハッシュを切り離し
  2. そのSaltを利用して、入力されたパスワードからパスワードハッシュを計算
  3. 照合

2.0.0のMicrosoft.AspNet.Identity.PasswordHasher.VerifyHashedPassword()も、vNextのコードで生成したハッシュを使って検証したら成功したので、多分同じロジック。

参考:Identity/src/Microsoft.AspNet.Identity/Crypto.cs

Roleによる認可的な

Controllerで

if(this.User.IsInRole("Admin"))
{
}

とか
[Authorize(Roles="Admin")]
public ActionResult Index()
{
    return View();
}

とか。

Viewで

@if (this.User.IsInRole("Admin"))
{
}

とか。

7月 062012
 
問題

VisualStudioの「配置パッケージの作成」や、MSBuildのターゲットPackageで作成したデプロイパッケージは、同時に作成されるdeploy.cmdでデプロイすることが可能である。
方法: deploy.cmd ファイルを使用して配置パッケージをインストールする

これを用いる際、msdeployの追加フラグを指定することが可能だが、=を含むフラグ値を指定する場合は以下のように指定するようreadmeに注意書きがある。

注意: 次の例に示すように、等号 (=) を含む任意のフラグ値は二重引用符で囲む必要があります。これにより、パッケージに含まれるデータベースの配置がスキップされます:
“-skip:objectName=dbFullSql”

ところが、実際にこの通り指定するとエラーとなってしまう(少なくとも手元の環境では)。

エラー: 引数 ‘”-skip:objectName=dbFullSql”‘ を認識できません。引数はすべて “-” で始まります。
エラー数: 1。

解決策

上記リンクにある通り、フラグ値を_MsDeployAdditionalFlags環境変数に設定することで対応可能。

Web 配置 コマンドを、__MsDeployAdditionalFlags 環境変数を設定して指定することもできます。

SET _MsDeployAdditionalFlags=-skip:objectName=dbFullSql
example.deploy.cmd /T /M:hostname /U:UserName /P:Password
7月 062012
 

VisualStudio標準では、XML-Document-Transformで差分を記述し、元のファイルを変換するという方法となる。
Web アプリケーション プロジェクト配置の Web.config 変換構文

以下のようなファイルを用意し、Web.Debug.configやWeb.Release.configといったファイル名にすれば、Debugビルド時にはWeb.Debug.configファイルを、Releaseビルド時にはweb.Release.configファイルがWeb.configとマージされる。

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="Sample.Properties.Settings.ConnectionString"
      connectionString="Data Source=SAMPLE;User ID=SAMPLE;Password=SAMPLE;Unicode=True;"
      providerName="System.Data.OracleClient"
      xdt:Transform="Replace"
      xdt:Locator="Match(name)"/>
  </connectionStrings>
</configuration>

Debug/Releaseだけでは2環境しか対応できないが、3環境以上対応したい場合もそれなりにある。
その場合はProjectConfigTransformFileNameプロパティを変更することで対応可能。

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition=" '$(DeploymentEnvironment)' != '' ">
    <ProjectConfigTransformFileName>@(_VSProjectConfigFileName->'%(FileName).$(DeploymentEnvironment)%(Extension)')</ProjectConfigTransformFileName>
  </PropertyGroup>
</Project>

というようなtargetsファイルをImportしておけば、

msbuild /t:Package /p:DeploymentEnvironment=production

とかやった場合にWeb.production.configを用いてWeb.configが変換される。
これはMicrosoft.Web.Publishing.targetsの内部動作に依存している。
VisualStudioに含まれるtargetsであるため、VSをインストールしないと利用できない。

ここでDeploymentEnvironmentのみ変更してビルドしなおした場合、Web.configが最新状態であるとみなされて変換されないことがある。

PostTransformWebConfig:
  Web.production.config を使用して Web.config を obj\Release\TransformWebConfig\transformed\Web.config に変換しました。
PipelineTransformPhase:
  パイプラインの発行の変換フェーズ
PreAutoParameterizationWebConfigConnectionStrings:
  obj\Release\CSAutoParameterize\original\Web.config への obj\Release\TransformWebConfig\transformed\Web.config のコピーをスキップします。ファイル obj\Release\CSAutoParameterize\original\Web.config は最新のものです
AutoParameterizationWebConfigConnectionStringsCore:
すべての出力ファイルが入力ファイルに対して最新なので、ターゲット "AutoParameterizationWebConfigConnectionStringsCore" を省略します。

この場合、Cleanターゲットも実行するようにすれば対処可能。

PostTransformWebConfig:
  Web.production.config を使用して Web.config を obj\Release\TransformWebConfig\transformed\Web.config に変換しました。
PipelineTransformPhase:
  パイプラインの発行の変換フェーズ
PreAutoParameterizationWebConfigConnectionStrings:
  ディレクトリ "D:\Jenkins\workspace\example\obj\Release\CSAutoParameterize\transformed\" を作成しています。
  obj\Release\TransformWebConfig\transformed\Web.config を obj\Release\CSAutoParameterize\original\Web.config にコピーしています。
AutoParameterizationWebConfigConnectionStringsCore:
  ソース ファイルを変換しています: D:\Jenkins\workspace\example\obj\Release\TransformWebConfig\transformed\Web.config
    変換ファイルを適用しています: 
          
            
              
            
          
    出力ファイル: obj\Release\CSAutoParameterize\transformed\Web.config
  変換に成功しました