WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

ページャーの移植

by WebSurfer 2011年10月23日 19:03

BlogEngine.NET バージョン 2.0 に使用されている新しいページャーを、バージョン 1.6.1 のこのブログに移植しました。

新旧ページャーの比較

上の画像では、比較のため、旧ページャー(上の <<前のブログ    次のブログ>> と表示されているもの)と新ページャー(下のページ番号が表示されているもの)を一緒に表示してあります。

具体的な移植方法は以下の通りです。

  • バージョン 2.0 のページャー(カスタムコントロール App_Code/Controls/PostPager.cs)をコピーしてきます。その際、W3C 検証にパスしないAPML フィルターの問題 は処置しておきましょう。また、バージョン 2.0 では名前空間が App_Code.Controls となっているので、バージョン 1.6.1 に合わせて Controls に変更しておきます。
  • User Control/PostList.ascx.cs にバージョン 2.0 のページャーを追加します。さらに、バージョン 1.6.1 のページャーを style="display: none" を追加して消去します。下のサンプルを参考にしてください。
  • User Control/PostList.ascx.cs の Posts プロパティに、ページャーに Post のコレクションへの参照を設定するためのコードを一行追加します。下のサンプルを参考にしてください。
  • 最後に、css を移植します。バージョン 2.0 の Style/Global.css の最後の方にページャー関係のスタイル定義があるので、それをバージョン 1.6.1 の css ファイルにコピーします。バージョン 1.6.1 には Style/Global.css というファイルはないので、自分は、当該テーマの style.css にコピーしました。

User Control/PostList.ascx

<%@ Control Language="C#" 
  AutoEventWireup="true" 
  CodeFile="PostList.ascx.cs" 
  EnableViewState="false" 
  Inherits="User_controls_PostList" %>

<div runat="server" id="posts" class="posts" />

<div id="postPaging" style="display: none">
  <a runat="server" 
    ID="hlPrev" 
    style="float:left">
    << <%=Resources.labels.previousPosts %>
  </a>
  <a runat="server" 
    ID="hlNext" 
    style="float:right">
    <%=Resources.labels.nextPosts %> >>
  </a>
</div>

<%--2011/10/23 BlogEngine.NET 2.0 のページャー 
  (App_Code/Controls/PostPager.cs) を移植。
  旧ページャーは div id="postPaging" に 
  style="display: none" として消去。--%>
<div style="clear:both; display:block">
  <blog:PostPager ID="pager1" 
    runat="server">
  </blog:PostPager>
</div>

User Control/PostList.ascx.cs

// ・・・前略・・・

public partial class User_controls_PostList : UserControl
{

  // ・・・中略・・・

  private List<IPublishable> _Posts;
  /// <summary>
  /// The list of posts to display.
  /// </summary>
  public List<IPublishable> Posts
  {
    get 
    { 
      return _Posts; 
    }
    set 
    { 
      _Posts = value;

      // 2011/10/23 BlogEngine.NET 2.0 のページャー
      // (App_Code/Controls/PostPager.cs) を移植した
      // ので以下のコードを追加。
      this.pager1.Posts = value;
    }

  // ・・・中略・・・

}

Tags:

BlogEngine.NET

パスワードに有効期限を設定

by WebSurfer 2011年10月22日 16:31

Forms 認証でパスワードに有効期限を設定するにはどうしたらよいでしょうか?

有効期限切れパスワードの変更

有効期限を知るためのデータ(例えば、最初にアカウントを作成した日時またはパスワードを変更した日時)をデータベースに記録し、ユーザーがログインした際にそのデータを取得して期限が過ぎているか否かの判断をするという操作が必要です。

組み込みの機能にそのようなものはないと思っていましたが、よく調べてみたら、標準の Forms 認証用 SQL Server データベースの aspnet_Membership テーブルに LastPasswordChangedDate というフィールドがあり、それを取得するために MembershipUser.LastPasswordChangedDate プロパティ が用意されていました。

これを利用すれば、パスワードに有効期限を設け、ユーザーがログインする際に有効期限が過ぎていたら ChangePassword コントロール を表示して、ユーザーにパスワード変更を促すというような操作が簡単に可能になります。

以下のコードは、パスワードの有効期限を 90 日とし、ユーザーがログインする際に 90 日を過ぎていたら Login コンロトールを非表示にするとともに ChangePassword コントロールを表示し(上の画像がそれです)、パスワードを変更したら Login コンロトールを再度表示して新しいパスワードでログインするというシナリオになっています。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Security" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

  double expireDays = 90;

  protected void Login1_LoggingIn(object sender, 
    LoginCancelEventArgs e)
  {
    MembershipUser user = 
      Membership.GetUser(Login1.UserName);

    if (user == null)
    {
      // MembershipUser が取得できなければその後の
      // 処置は Login コントロールに任せる。
      return;
    }

    if (user.LastPasswordChangedDate.AddDays(expireDays) <
      DateTime.Now)
    {
      Msg.Visible = true;
      Msg.Text = "パスワードが有効期限を過ぎています。";
      ChangePassword1.UserName = Login1.UserName;
      ChangePasswordPanel.Visible = true;
      LoginPanel.Visible = false;
      e.Cancel = true;
    }
    else
    {
      Msg.Visible = false;
    }
  }

  protected void _ChangingPassword(object sender, 
    LoginCancelEventArgs e)
  {
    if (ChangePassword1.CurrentPassword == 
      ChangePassword1.NewPassword)
    {
      Msg.Visible = true;
      Msg.Text = "新旧パスワードが同じです。";
      e.Cancel = true;
    }
    else
    {
      Msg.Visible = false;
    }        
  }

  protected void _ChangedPassword(object sender, EventArgs e)
  {
    ChangePasswordPanel.Visible = false;
    LoginPanel.Visible = true;
    Msg.Visible = true;
    Msg.Text = "新しいパスワードでログインしてください。";
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Login</title>
</head>
<body>
  <form id="form1" runat="server">
    <h3>有効期限つきパスワードでのログイン操作</h3>

    <asp:Label id="Msg" 
      runat="server" 
      ForeColor="maroon"  
      Visible="False" />
    <br />

    <asp:Panel ID="LoginPanel" 
      runat="server">
      <asp:Login ID="Login1" 
        runat="server" 
        DisplayRememberMe="False" 
        OnLoggingIn="Login1_LoggingIn">
      </asp:Login>
    </asp:Panel>

    <asp:Panel ID="ChangePasswordPanel" 
      runat="server" 
      Visible="False">
      <asp:ChangePassword ID="ChangePassword1" 
        runat="server" 
        DisplayUserName="True" 
        OnChangingPassword="_ChangingPassword" 
        OnChangedPassword="_ChangedPassword" 
        CancelDestinationPageUrl="~/Default.aspx">
      </asp:ChangePassword>
    </asp:Panel>
  </form>
</body>
</html>

参考にしたのは MembershipUser.LastPasswordChangedDate プロパティChangePassword.CurrentPassword プロパティ のサンプルコードです。

Tags: ,

Authentication

厳密な名前付きアセンブリ

by WebSurfer 2011年9月13日 22:37

サンデープログラマーの自分が、作成したアセンブリに厳密名を付けることはないですが、わけあって厳密名の付け方についていろいろ調べましたので、備忘録として書いておきます。

まず、厳密名 (Strong Name) とは何かですが、MSDN ライブラリ 厳密な名前付きアセンブリ によると「単純テキスト名(アセンブリ名)、バージョン番号、カルチャ情報から成るアセンブリの識別子と、公開キーおよびデジタル署名」だそうです。

web.config で、ライブラリへの参照や HTTP モジュールの参照を設定する際以下のようにしますが、これが厳密名を指定したことになるようです。

<add 
  assembly="System.Core, 
  Version=3.5.0.0, 
  Culture=neutral, 
  PublicKeyToken=B77A5C561934E089"/>

<add 
  name="ScriptModule" 
  type="System.Web.Handlers.ScriptModule, 
    System.Web.Extensions, 
    Version=3.5.0.0, 
    Culture=neutral, 
    PublicKeyToken=31BF3856AD364E35"/>

厳密な名前を付ける理由や、それが推奨されるケース/されないケースについては MSDN ライブラリの マネージ アプリケーションに対する厳密な名前による署名 に書いてあるのでそちらを参照してください。手抜きですみません。(笑)

厳密名のうち、アセンブリ名、バージョン番号、カルチャ情報は開発者が自分で設定する(というより、デフォルトで設定されている)ものです。下の画像にそれらが示されています。

Visual Studio のアセンブリ情報の画面

厳密名のなかで、公開キーとデジタル署名、および公開キートークン (PublicKeyToken) が具体的に何かよく分かってなかったので調べてみました。

アセンブリにデジタル署名するには、まず、秘密キー/公開キーペアから成るキーファイルを作成します。次に、アセンブリの一部分のハッシュを作成し、それを秘密キーで暗号化し、公開キーとともにアセンブリに追加(署名)します。

アセンブリをロードする際、アセンブリに含まれる公開キーと秘密キーで暗号化されたハッシュを取り出し、暗号化されたハッシュを公開キーで復号します。次に、ロードするアセンブリ自体のハッシュを作成して、それと復号したハッシュとを比較して一致することを確認します。これにより正しいアセンブリがロードされることを保障できます。加えて、改ざんされていないかどうかもチェックできますので、セキュリティも向上するということのようです。

さて、キーファイルの作成とアセンブリの署名をどのように行うかですが、Visual Studio 2008, 2010(未確認ですが、たぶん 2005 も)には、プロパティページに[署名]タブがありますので、それでキーペアの作成が可能です。キーペアを作成した上でビルドすればアセンブリに署名できます。下の画像を参照してください。ちなみに以前(たぶん Visual Studio 2003 以前)は Sn.exe (厳密名ツール)Al.exe (アセンブリ リンカー) を使って手動で行っていたようです。

Visual Studio の厳密な名前キーの作成画面

上の画面で[アセンブリの署名]チェックボックスにチェックを入れ、[厳密な名前のキー ファイルを選択してください]ボックスの一覧の[<新規作成...>」を選択すると[厳密な名前キーの作成]ダイアログボックスが表示されます。

[厳密な名前キーの作成]ダイアログボックスで、新しいキーファイルの名前を入力し、さらに、必要に応じてパスワードを入力します。パスワードを指定すると、Personal Information Exchange (.pfx) ファイルが作成され、指定しないと Strong Name Key (.snk) ファイルが作成されます。[OK]をクリックすると、以下の画像のようにキーファイルが作成されます。

Visual Studio で作成したキーファイル

.pfx ファイルと .snk ファイルの中身が具体的にどのように違うかは調べていませんが、MSDN ライブラリ [キー ファイルのインポート] ダイアログ ボックス によると、キーファイルをインポートするには .pfk ファイル形式にする必要があるそうです。

アセンブリが正しくロードされるという保障も、改ざんが防止できるというセキュリティ機能も、キーファイルに含まれる秘密キーをアセンブリの提供者(ソフトウェア会社)のみが持っているという前提の上に成り立っています。従って、このキーファイルはソフトウェア会社に固有となるようにし、流出しないよう厳重に管理する必要があるそうです。

上の画像のように、キーファイルを作成してプロジェクトに配置した後は、ビルドすれば自動的にキーファイルに含まれる公開キーと秘密キーを使ってアセンブリに署名されます。

そのようにして厳密名を付けたアセンブリを参照する例を書きます。例えば HTTP モジュールを dll として bin フォルダに配置する場合を考えます。web.config でアセンブリ名、バージョン番号、カルチャ情報、公開キートークンを以下のように設定します

<add 
  name="HelloWorldModule" 
  type="MyHttpModule.HelloWorldModule, 
    MyHttpModule, 
    Version=1.0.0.0, 
    Culture=neutral, 
    PublicKeyToken=90cefab791a0b403"/>

アセンブリ名、バージョン番号、カルチャ情報はすぐ分かりますが、問題は公開キートークン(PublicKeyToken)です。公開キートークンとは、公開キーにハッシュをかけて抽出した値の最後の 8 バイトです。公開キーのサイズは 128 バイトもあるので、それをそのまま参照に使うと、参照しているアセンブリが 1 つ増えるたびに 128 バイトずつサイズが増えてしまうことになります。それではサイズが増えすぎて困るので、そのようにしているらしいです。

公開キートークンを取得するには Sn.exe (厳密名ツール) を利用します。コマンドラインから -T オプションを使用して以下のようにします。

sn.exe を使用して公開キートークンを取得

このようにして web.config で厳密名(アセンブリ名、バージョン番号、カルチャ情報、公開キートークン)を指定すると、アセンブリをロードする際それらの 項目をチェックし、矛盾があると実行時に以下の画像ようなエラーが出ます。

厳密名が異なる場合のエラー画面

最後に、Visual Studio のプロパティページの[署名]タブの[遅延署名のみ(Y)]について簡単に書きます。

これは組織が厳重に保護している(すなわち、一般の開発者にはアクセスが許可されていない)キーファイル(特に秘密キー)を使用しなくても、開発に支障がないようにするためのオプションです。

秘密キーがないと署名(アセンブリのハッシュを取って、それを秘密キーで暗号化した情報のアセンブリへの埋め込み)ができません。それでは開発に支障が出るので、アセンブリに署名をせずに公開キーだけを埋め込み、一時的に署名の検証を無効にして開発を進められるようにします。開発が完了した後、秘密キーにアクセスできる限られた者が、秘密キーを使って署名してリリースします。後で署名するので「遅延署名 (Delay Sign)」と言うらしいです。

詳しくは、第2回 アセンブリのアイデンティティ が参考になると思います。

Tags:

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年5月  >>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar