ASP.NET 簡易ユーザ管理

[Home]


はじめに

簡易ユーザ管理 ASP.NET アプリケーションは、厳密なユーザ管理が必要でない簡易なサイトで使うためのウェブアプリケーションです。


概要

 

データベース

データベースはデフォルトで "User" になっている。必要なテーブルはテーブルは、"dbo.Users" だけである。下にテーブル作成 SQL を示す。

USE [User];
GO
CREATE TABLE dbo.Users (
  UserId VARCHAR(20) NOT NULL PRIMARY KEY,
  Name NVARCHAR(40),
  [Password] VARCHAR(200),
  Info NVARCHAR(100),
  CreationDate CHAR(8)
);
GO
-- 初期パスワードは 0000
INSERT INTO dbo.Users VALUES('admin',N'組み込み管理者',
'4a7d1ed414474e4033ac29ccb8653d9b',N'組み込みユーザのため削除不可','20161231');
GO
 

デフォルトでは、Windows 認証で SQL Server にログインするようになっている。IIS で動作させる場合、DefaultAppPool という偽装ユーザで動作するので、User データベースに "IIS APPPOOL\DefaultAppPool" ユーザを登録する必要がある。詳細は下記を参照すること。

ASP.NET : IIS に発行したウェブアプリで SQL Server にアクセスできない件

 

ログイン画面

ユーザIDとパスワードを入力して Login ボタンを押すと、デフォルトではユーザ一覧画面を表示する。アプリケーションに組み込む場合は、これを遷移先のページに変更する。「MD5を計算」ボタンをクリックすると、パスワードに入力した文字列の MD5 を表示する。



Login.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Login.aspx.vb" Inherits="Users.Login" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Login</title>
    <link rel="stylesheet" href="css/default.css" />
</head>
<body>
    <form id="formLogin" runat="server">
        <h1>ログイン</h1>
    <div class="row">
        <span class="col-2" style="text-align:right;">
            ログイン
        </span>
        <span class="col-4">
            <asp:TextBox ID="UserId" runat="server"></asp:TextBox>
        </span>
    </div>
    <div class="row">
        <span class="col-2" style="text-align:right;">
            パスワード
        </span>
        <span class="col-4">
            <asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
        </span>
    </div>
    <div class="row">
        <span class="col-2">

        </span>
        <span class="col-4">
            <asp:Button ID="BtnLogin" runat="server" Text="Login" />
            <asp:Button ID="BtnMd5" runat="server" Text="MD5を計算" />
        </span>   
    </div>
    <div class="row">
        <asp:Label ID="Message" runat="server" Text=""></asp:Label>
    </div>
    </form>
</body>
</html>


Login.aspx.vb

''' <summary>
''' ログインページ
''' </summary>
''' <remarks></remarks>
Public Class Login
    Inherits System.Web.UI.Page

    ''' <summary>
    ''' ページがロードしたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Session("UserId") = ""
    End Sub

    ''' <summary>
    ''' ログインボタン
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub BtnLogin_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnLogin.Click
        Dim ds As New DataSetUsers
        Dim adapter As New DataSetUsersTableAdapters.UsersTableAdapter
        adapter.Fill(ds.Users)
        Dim rs = From x In ds.Users Where x.UserId = UserId.Text And x.Password = GetMd5(Password.Text)

        If rs.Any() Then
            Message.Text = "OK"
            Session("UserId") = UserId.Text
            Server.Transfer("UsersList.aspx")
        Else
            Message.Text = "ログインできません。"
        End If
    End Sub

    ''' <summary>
    ''' MD5 を計算する。
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub BtnMd5_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnMd5.Click
        Message.Text = GetMd5(Password.Text)
    End Sub

    ''' <summary>
    ''' MD5 を計算する。
    ''' </summary>
    ''' <param name="str"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetMd5(ByVal str As String) As String
        Dim sb As New StringBuilder
        Dim md5 As New System.Security.Cryptography.MD5CryptoServiceProvider
        Dim data As Byte() = System.Text.Encoding.UTF8.GetBytes(str)
        Dim bytes As Byte() = md5.ComputeHash(data)
        For Each b As Byte In bytes
            sb.Append(String.Format("{0:x2}", b))
        Next
        Return sb.ToString()
    End Function
End Class

 

管理画面

ユーザ一覧画面

ログインに成功するとユーザ一覧画面に遷移する。



UserList.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="UsersList.aspx.vb" Inherits="Users.UsersList" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <titleユーザ一覧></titleユーザ一覧>
    <link rel="stylesheet" href="~/css/default.css" />
</head>
<body>
    <form id="form1" runat="server">
    <div class="row">
        <h1>ユーザ一覧</h1>
        <hr />
    </div>
    <div class="row">
        <span class="col-6">
            <asp:HyperLink ID="HlLogout" runat="server" NavigateUrl="index.html">ログアウト</asp:HyperLink>&nbsp;|&nbsp;
            <asp:HyperLink ID="HlAppend" runat="server" NavigateUrl="Append.aspx">ユーザ追加</asp:HyperLink>&nbsp;|&nbsp;
            <asp:HyperLink ID="HlDelete" runat="server" NavigateUrl="Delete.aspx">ユーザ削除</asp:HyperLink>&nbsp;|&nbsp;
            <asp:HyperLink ID="HlChange" runat="server" NavigateUrl="ChangePassword.aspx">パスワード変更</asp:HyperLink>
        </span>
        <span class="col-4" style="text-align:right;color:crimson;">現在のユーザ:
 <asp:Label ID="LbUserId" runat="server" Text=""></asp:Label></span>
    </div>
        <div class="row">
            <asp:Literal ID="Literal1" runat="server"></asp:Literal>
        </div>
    </form>
</body>
</html>


UserList.aspx.vb

''' <summary>
''' ユーザ一覧
''' </summary>
''' <remarks></remarks>
Public Class UsersList
    Inherits System.Web.UI.Page

    ''' <summary>
    ''' ロードしたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
 Handles Me.Load
        If String.IsNullOrEmpty(Session("UserId")) Then
            Response.Redirect("index.html")
        Else
            LbUserId.Text = Session("UserId")
            ShowUsers()
        End If
    End Sub

    ''' <summary>
    ''' ユーザ一覧を表示する。
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub ShowUsers()
        Dim ds As New DataSetUsers
        Dim adapter As New DataSetUsersTableAdapters.UsersTableAdapter
        adapter.Fill(ds.Users)
        Dim rs = From x In ds.Users Select x
        Dim sb As New StringBuilder
        sb.Append("<table>")
        sb.Append(<tr><th>UserId</th><th>Name</th><th>Password</th><th>Info</th>
<th>CreationDate</th></tr>)
        For Each row As DataSetUsers.UsersRow In rs.ToArray()
            sb.Append("<tr><td>" & row.UserId & "</td>")
            sb.Append("<td>" & row.Name & "</td>")
            sb.Append("<td>" & row.Password & "</td>")
            sb.Append("<td>" & row.Info & "</td>")
            sb.Append("<td>" & row.CreationDate & "</td></tr>")
        Next
        sb.Append("</table>")
        Literal1.Text = sb.ToString()
    End Sub
End Class

 

ユーザ追加画面

ユーザ一覧画面の「ユーザ追加」メニューをクリックすると、本画面が表示される。



Append.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Append.aspx.vb" Inherits="Users.Append" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>ユーザの追加</title>
    <link rel="stylesheet" href="~/css/default.css" />
</head>
<body>
    <form id="form1" runat="server">
        <h1>ユーザの追加</h1>
        <hr />
        <div class="row" style="color:crimson;">
            <span class="col-2"><a href="UsersList.aspx">ユーザ一覧</a>
&nbsp;<a href="index.html">ログアウト</a></span>
            <span class="col-4" style="text-align:right;">現在のユーザ: <asp:Label ID="LbUserId" runat="server" Text=""></asp:Label></span>
        </div>
    <div class="row">
        <span class="col-2" style="text-align:right;">UserId</span>
        <span class="col-4">
            <asp:TextBox ID="UserId" runat="server"></asp:TextBox></span>
    </div>
    <div class="row">
        <span class="col-2" style="text-align:right;">Name</span>
        <span class="col-4">
            <asp:TextBox ID="Name" runat="server"></asp:TextBox></span>
    </div>
    <div class="row">
        <span class="col-2" style="text-align:right;">Password</span>
        <span class="col-4">
            <asp:TextBox ID="Password" runat="server"></asp:TextBox></span>
    </div>
    <div class="row">
        <span class="col-2" style="text-align:right;">Info</span>
        <span class="col-4">
            <asp:TextBox ID="Info" runat="server" Width="350px"></asp:TextBox>
</span>
    </div>
    <div class="row">
        <span class="col-2" style="text-align:right;"></span>
        <span class="col-4">
            <asp:Button ID="BtnAppend" runat="server" Text="追加する" /></span>
    </div>
    <div class="row">
        <asp:Label ID="LbMessage" runat="server" Text=""></asp:Label>
    </div>
    </form>
</body>
</html>

Append.aspx.vb

''' <summary>
''' ユーザの追加
''' </summary>
''' <remarks></remarks>
Public Class Append
    Inherits System.Web.UI.Page

    ''' <summary>
    ''' ページがロードしたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
 Handles Me.Load
        If String.IsNullOrEmpty(Session("UserId")) Then
            Server.Transfer("index.html")
        ElseIf Session("UserId") <> "admin" Then
            LbMessage.Text = "エラー: 管理ユーザのみの機能です。"
            LbUserId.Text = Session("UserId")
            BtnAppend.Enabled = False
        Else
            LbUserId.Text = Session("UserId")
        End If
    End Sub

    ''' <summary>
    ''' ボタンがクリックされたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub BtnAppend_Click(ByVal sender As Object, ByVal e As System.EventArgs)
 Handles BtnAppend.Click
        Dim db As New UserEntities
        Dim row As New Users
        row.UserId = UserId.Text
        row.Name = Name.Text
        row.Password = Login.GetMd5(Password.Text)
        row.Info = Info.Text
        row.CreationDate = String.Format("{0:yyyyMMdd}", DateTime.Today)
        Try
            db.Users.Add(row)
            db.SaveChanges()
            LbMessage.Text = "ユーザを追加しました。"
        Catch ex As Exception
            LbMessage.Text = "エラー:" & ex.Message
        End Try
    End Sub
End Class

ユーザ削除画面

ユーザ一覧画面の「ユーザ削除」メニューをクリックすると、本画面が表示される。


Delete.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Delete.aspx.vb" Inherits="Users.Delete" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>ユーザの削除</title>
    <link rel="stylesheet" href="~/css/default.css" />
</head>
<body>
    <form id="form1" runat="server">
    <h1>ユーザの削除</h1>
        <hr />
    <div class="row" style="color:crimson;">
        <span class="col-2"><a href="UsersList.aspx">ユーザ一覧</a>&nbsp;|&nbsp;<a href="index.html">ログアウト</a></span>
        <span class="col-4" style="text-align:right;">現在のユーザ: <asp:Label ID="LbUserId" runat="server" Text=""></asp:Label></span>
    </div>
        <div class="row">
            <span class="col-2" style="text-align:right;">
                UserId
            </span>
            <span class="col-2">
                <asp:TextBox ID="UserId" runat="server"></asp:TextBox>
            </span>
        </div>
        <div class="row">
            <span class="col-2" style="text-align:right;">
                
            </span>
            <span class="col-2">
                <asp:Button ID="BtnDelete" runat="server" Text="削除する" />
            </span>
        </div>
        <div class="row">
            <asp:Label ID="LbMessage" runat="server" Text=""></asp:Label>
        </div>
    </form>
</body>
</html>


Delete.aspx.vb

''' <summary>
''' ユーザの削除
''' </summary>
''' <remarks></remarks>
Public Class Delete
    Inherits System.Web.UI.Page

    ''' <summary>
    ''' ページがロードしたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If String.IsNullOrEmpty(Session("UserId")) Then
            Server.Transfer("index.html")
        ElseIf Session("UserId") <> "admin" Then
            LbMessage.Text = "エラー: 管理ユーザのみの機能です。"
            LbUserId.Text = Session("UserId")
            BtnDelete.Enabled = False
        Else
            LbUserId.Text = Session("UserId")
        End If
    End Sub

    ''' <summary>
    ''' 削除のタン
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub BtnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnDelete.Click
        If UserId.Text = "admin" Then
            LbMessage.Text = "admin は組み込みユーザのため削除できません。"
            Return
        End If

        Dim db As New UserEntities
        Dim row As New Users
        Dim rs = From x In db.Users Where x.UserId = UserId.Text Select x

        Try
            row = rs.ToArray()(0)
            db.Users.Remove(row)
            db.SaveChanges()
            LbMessage.Text = "削除しました。"
        Catch ex As Exception
            LbMessage.Text = "エラー:" & ex.Message
        End Try
    End Sub
End Class

パスワード変更画面

ユーザ一覧画面の「パスワード変更」メニューをクリックすると、本画面が表示される。


ChagePassword.aspx

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="ChangePassword.aspx.vb" Inherits="Users.ChangePassword" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>パスワードの変更</title>
    <link rel="stylesheet" href="~/css/default.css" />
</head>
<body>
    <form id="form1" runat="server">
    <h1>パスワードの変更</h1>
        <hr />
    <div class="row" style="color:crimson;">
        <span class="col-2"><a href="UsersList.aspx">ユーザ一覧</a>
&nbsp;|&nbsp;<a href="index.html">ログアウト</a></span>
        <span class="col-4" style="text-align:right;">現在のユーザ: <asp:Label ID="LbUserId" runat="server" Text=""></asp:Label></span>
    </div>
    <div class="row">
         <span class="col-2" style="text-align:right;">
             UserId
             </span>
         <span class="col-4">
             <asp:TextBox ID="UserId" runat="server"></asp:TextBox>
             </span>
    </div>
    <div class="row">
         <span class="col-2" style="text-align:right;">
             Password
             </span>
         <span class="col-4">
             <asp:TextBox ID="Password" runat="server"></asp:TextBox>
             </span>
    </div>
    <div class="row">
         <span class="col-2" style="text-align:right;">
             
             </span>
         <span class="col-4">
             <asp:Button ID="BtnChange" runat="server" Text="変更する" />
             </span>
    </div>
    <div class="row">
        <asp:Label ID="LbMessage" runat="server" Text=""></asp:Label>
    </div>
    </form>
</body>
</html>


ChagePassword.aspx.vb

''' <summary>
''' パスワードを変更する
''' </summary>
''' <remarks></remarks>
Public Class ChangePassword
    Inherits System.Web.UI.Page

    ''' <summary>
    ''' ページがロードしたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If String.IsNullOrEmpty(Session("UserId")) Then
            Server.Transfer("index.html")
        Else
            LbUserId.Text = Session("UserId")
        End If
    End Sub

    ''' <summary>
    ''' 変更するボタン
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Sub BtnChange_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnChange.Click
        If UserId.Text <> Session("UserId") Then
            LbMessage.Text = "エラー: 他ユーザのパスワードは変更できません。"
            BtnChange.Enabled = False
        End If
        Dim db As New UserEntities
        Dim row As New Users
        Dim rs = From x In db.Users Where x.UserId = UserId.Text Select x

        Try
            row = rs.ToArray()(0)
            row.Password = Login.GetMd5(Password.Text)
            db.SaveChanges()
            LbMessage.Text = "変更しました。"
        Catch ex As Exception
            LbMessage.Text = "エラー:" & ex.Message
        End Try

    End Sub
End Class

 

モデル

DataSetUsers.xsd


ModelUsers.edmx

 

WCF ウェブサービス

ServiceUsers.svc


ServiceUsers.svc.vb

' メモ: コンテキスト メニューの [名前の変更] コマンドを使用すると、コード、svc、および config ファイルで同時にクラス名 "ServiceUsers" を変更できます。
' 注意: このサービスをテストするために WCF テスト クライアントを起動するには、ソリューション エクスプローラーで ServiceUsers.svc または ServiceUsers.svc.vb を選択し、デバッグを開始してください。
Public Class ServiceUsers
    Implements IServiceUsers

    ''' <summary>
    ''' ユーザ一覧を得る。
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetUserList() As String() Implements IServiceUsers.GetUserList
        Dim result As New List(Of String)
        Dim ds As New DataSetUsers
        Dim adapter As New DataSetUsersTableAdapters.UsersTableAdapter
        adapter.Fill(ds.Users)
        Dim sb As New System.Text.StringBuilder
        For Each row As DataRow In ds.Users.Rows
            sb.Append(row("UserId") & ",")
            sb.Append(row("Name") & ",")
            sb.Append(row("Password") & ",")
            sb.Append(row("Info") & ",")
            sb.Append(row("CreationDate"))
            result.Add(sb.ToString())
            sb.Clear()
        Next
        Return result.ToArray()
    End Function

    ''' <summary>
    ''' ユーザ一覧をCSVで置き換える。
    ''' </summary>
    ''' <param name="csv"></param>
    ''' <remarks></remarks>
    Public Sub ReplaceUserList(ByVal csv As String()) 
Implements IServiceUsers.ReplaceUserList
        Dim items As String()
        Dim db As New UserEntities
        db.Database.ExecuteSqlCommand("DELETE FROM dbo.Users WHERE UserId <> 'admin'")
        For Each line As String In csv
            items = line.Split({","c})
            db.Users.Add(New Users With {.UserId = items(0), .Name = items(1), _
    .Password = Login.GetMd5(items(2)), _
    .Info = items(3), .CreationDate = items(4)})
        Next
        db.SaveChanges()
    End Sub
End Class


IServiceUsers.vb

Imports System.ServiceModel

' メモ: コンテキスト メニューの [名前の変更] コマンドを使用すると、
コードと config ファイルの両方で同時にインターフェイス名 "IServiceUsers" を変更できます。
<ServiceContract()>
Public Interface IServiceUsers

    ''' <summary>
    ''' ユーザ一覧をCSVとして得る。
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <OperationContract()>
    Function GetUserList() As String()

    ''' <summary>
    ''' ユーザ一覧をCSVで置き換える。
    ''' </summary>
    ''' <param name="csv"></param>
    ''' <remarks></remarks>
    <OperationContract()>
    Sub ReplaceUserList(ByVal csv As String())
End Interface


テストプログラム

テストプログラムではサービス参照で、この WCF サービスを設定する。


ユーザ一覧を表示する例

Module Module1

    Sub Main()
        Dim client As New ServiceReference1.ServiceUsersClient()
        ' 'client' 変数を使用して、このサービスで操作を呼び出してください。
        Dim csv As String() = client.GetUserList()

        For Each line As String In csv
            Console.WriteLine(line)
        Next
        ' 常にクライアントを閉じてください。
        client.Close()
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub

End Module


CSV をユーザ一覧としてデータベースに登録する例

Module Module1

    Sub Main()
        Dim csv As String() = {"user1,User1,1111,ユーザ1,20161210", _
"user2,User2,2222,ユーザ2,20161210", _
"user3,User3,3333,ユーザ3,20161210", "guest,Guest,guest,一時ユーザ,20161210"}
        Dim client As New ServiceReference1.ServiceUsersClient
        client.ReplaceUserList(csv)
        Console.WriteLine("ユーザリストを更新しました。")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub

End Module


Download