ASP.NET MVCアプリケーションにsimple Authentication and Authorizationを追加しようとしています。
私は基本的なフォーム認証に追加された機能を追加しようとしています(シンプルさとカスタムデータベース構造のため)
これが私のデータベース構造であると仮定します:ユーザー:ユーザー名パスワードロール(理想的にはいくつかの列挙。必要であれば文字列。現在、ユーザーは1つのロールしか持っていませんが、これは変わるかもしれません)
高レベルの問題:上記のデータベース構造を考えると、次のことができるようになりたいと思います。
現在、私が本当に確信しているのは認証方法です。その後、私は失われました。どの時点でユーザーロール(ログイン、すべての承認?)を取得するのかわかりません。私の役割は文字列ではない可能性があるため、User.IsInRole()にどのように適合するかはわかりません。
今、私は私が必要なものを達成する「単純な」ものを見つけていないので、ここで尋ねています。複数の例を見てきました。
認証の場合:
認可については、私は見た:
どんな援助も大歓迎です。しかし、私が多くの詳細を必要としているのではないかと恐れています。
文字列ではなく列挙型を使用できるカスタムAuthorizeAttribute
を構築します。承認する必要がある場合は、列挙型名+列挙値を追加して列挙を文字列に変換し、そこからIsInRole
を使用します。
承認されたユーザーにロールを追加するには、 http://www.eggheadcafe.com/articles/20020906の最初のコードのようなHttpApplication
AuthenticateRequest
イベントにアタッチする必要があります。 asp (ただし、大規模にネストされたifステートメントをガード句に変換します!)。
フォーム認証Cookieのユーザーロールをラウンドトリップするか、データベースから毎回取得することができます。
似たようなものを実装したと思います。
NerdDinnertutorial に基づく私の解決策は次のとおりです。
ユーザーにサインインするとき、次のようなコードを追加します:
var authTicket = new FormsAuthenticationTicket(
1, // version
userName, // user name
DateTime.Now, // created
DateTime.Now.AddMinutes(20), // expires
rememberMe, // persistent?
"Moderator;Admin" // can be used to store roles
);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);
次のコードをGlobal.asax.cs
に追加します:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
return;
FormsAuthenticationTicket authTicket;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
// retrieve roles from UserData
string[] roles = authTicket.UserData.Split(';');
if (Context.User != null)
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
これを実行した後、コントローラーアクションコードで [Authorize]
属性を使用することができます:
[Authorize(Roles="Admin")]
public ActionResult AdminIndex ()
さらに質問がある場合はお知らせください。
私はこのようなことをしました:
[Authorize]属性をコントローラーに割り当て、認証を必要とする
[Authorize(Roles = "Admin,Tech")]
または、アクセスを許可するには、たとえば、LoginおよびValidateUserコントローラーは以下の属性を使用します
[AllowAnonymous]
私のログインフォーム
<form id="formLogin" name="formLogin" method="post" action="ValidateUser">
<table>
<tr>
<td>
<label for="txtUserName">Username: (AD username) </label>
</td>
<td>
<input id="txtUserName" name="txtUserName" role="textbox" type="text" />
</td>
</tr>
<tr>
<td>
<label for="txtPassword">Password: </label>
</td>
<td>
<input id="txtPassword" name="txtPassword" role="textbox" type="password" />
</td>
</tr>
<tr>
<td>
<p>
<input id="btnLogin" type="submit" value="LogIn" class="formbutton" />
</p>
</td>
</tr>
</table>
@Html.Raw("<span id='lblLoginError'>" + @errMessage + "</span>")
</form>
フォームポストから呼び出されるログインコントローラーとValidateUserコントローラー
ユーザーの検証は、サービスにローカルなWindows ADコンテキストに対して検証するWCFサービスを介した認証ですが、これを独自の認証メカニズムに変更できます
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Security.Principal;
using MyMVCProject.Extensions;
namespace MyMVCProject.Controllers
{
public class SecurityController : Controller
{
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
Session["LoginReturnURL"] = returnUrl;
Session["PageName"] = "Login";
return View("Login");
}
[AllowAnonymous]
public ActionResult ValidateUser()
{
Session["PageName"] = "Login";
ViewResult retVal = null;
string loginError = string.Empty;
HttpContext.User = null;
var adClient = HttpContext.Application.GetApplicationStateWCFServiceProxyBase.ServiceProxyBase<UserOperationsReference.IUserOperations>>("ADService").Channel;
var username = Request.Form["txtUserName"];
var password = Request.Form["txtPassword"];
//check for ad domain name prefix
if (username.Contains(@"\"))
username = username.Split('\\')[1];
//check for the existence of the account
var acctReq = new UserOperationsReference.DoesAccountExistRequest();
acctReq.userName = username;
//account existence result
var accountExist = adClient.DoesAccountExist(acctReq);
if (!accountExist.DoesAccountExistResult)
{
//no account; inform the user
return View("Login", new object[] { "NO_ACCOUNT", accountExist.errorMessage });
}
//authenticate
var authReq = new UserOperationsReference.AuthenticateRequest();
authReq.userName = username;
authReq.passWord = password;
var authResponse = adClient.Authenticate(authReq);
String verifiedRoles = string.Empty;
//check to make sure the login was as success against the ad service endpoint
if (authResponse.AuthenticateResult == UserOperationsReference.DirectoryServicesEnumsUserProperties.SUCCESS)
{
Dictionary<string, string[]> siteRoles = null;
//get the role types and roles
if (HttpContext.Application["UISiteRoles"] != null)
siteRoles = HttpContext.Application.GetApplicationState<Dictionary<string, string[]>>("UISiteRoles");
string groupResponseError = string.Empty;
if (siteRoles != null && siteRoles.Count > 0)
{
//get the user roles from the AD service
var groupsReq = new UserOperationsReference.GetUsersGroupsRequest();
groupsReq.userName = username;
//execute the service method for getting the roles/groups
var groupsResponse = adClient.GetUsersGroups(groupsReq);
//retrieve the results
if (groupsResponse != null)
{
groupResponseError = groupsResponse.errorMessage;
var adRoles = groupsResponse.GetUsersGroupsResult;
if (adRoles != null)
{
//loop through the roles returned from the server
foreach (var adRole in adRoles)
{
//look for an admin role first
foreach (var roleName in siteRoles.Keys)
{
var roles = siteRoles[roleName].ToList();
foreach (var role in roles)
{
if (adRole.Equals(role, StringComparison.InvariantCultureIgnoreCase))
{
//we found a role, stop looking
verifiedRoles += roleName + ";";
break;
}
}
}
}
}
}
}
if (String.IsNullOrEmpty(verifiedRoles))
{
//no valid role we need to inform the user
return View("Login", new object[] { "NO_ACCESS_ROLE", groupResponseError });
}
if (verifiedRoles.EndsWith(";"))
verifiedRoles = verifiedRoles.Remove(verifiedRoles.Length - 1, 1);
//all is authenticated not build the auth ticket
var authTicket = new FormsAuthenticationTicket(
1, // version
username, // user name
DateTime.Now, // created
DateTime.Now.AddMinutes(20), // expires
true, // persistent?
verifiedRoles // can be used to store roles
);
//encrypt the ticket before adding it to the http response
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(authCookie);
Session["UserRoles"] = verifiedRoles.Split(';');
//redirect to calling page
Response.Redirect(Session["LoginReturnURL"].ToString());
}
else
{
retVal = View("Login", new object[] { authResponse.AuthenticateResult.ToString(), authResponse.errorMessage });
}
return retVal;
}
}
}
ユーザーは認証され、新しいIDを作成します
protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e)
{
if (FormsAuthentication.CookiesSupported == true)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
return;
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
// retrieve roles from UserData
if (authTicket.UserData == null)
return;
//get username from ticket
string username = authTicket.Name;
Context.User = new GenericPrincipal(
new System.Security.Principal.GenericIdentity(username, "MyCustomAuthTypeName"), authTicket.UserData.Split(';'));
}
}
私の_Layout.cshtmlの上部にあるサイトでは、このようなものがあります
{
bool authedUser = false;
if (User != null && User.Identity.AuthenticationType == "MyCustomAuthTypeName" && User.Identity.IsAuthenticated)
{
authedUser = true;
}
}
その後本文に
@{
if (authedUser)
{
<span id="loggedIn_userName">
<label>User Logged In: </label>@User.Identity.Name.ToUpper()
</span>
}
else
{
<span id="loggedIn_userName_none">
<label>No User Logged In</label>
</span>
}
}
ユーザーを「ロール内のユーザー」テーブルに追加します。コードでストアドプロシージャ「addusertorole」(そのようなもの)を使用して、さまざまなロールに追加します。 「ロール」テーブルで非常に簡単にロールを作成できます。
使用するテーブル:User、UsersInRole、Roles
組み込みのストアドプロシージャを使用して、これらのテーブルを操作します。あとは、属性を追加するだけです。
たとえば、ユーザーを選択してロールに追加するビューに「管理者」属性を設定できます。ストアドプロシージャを使用して、そのユーザーをロールに追加できます。