ASP.NET MVC 양식 인증 + 특성 권한 부여 + 단순 역할
ASP.NET MVC 응용 프로그램 에 간단한 인증 및 권한 부여 를 추가하려고 합니다.
기본 양식 인증에 몇 가지 추가 기능을 추가하려고합니다 (단순성과 사용자 정의 데이터베이스 구조로 인해)
이것이 내 데이터베이스 구조라고 가정합니다. 사용자 : 사용자 이름 암호 역할 (이상적으로는 일부 열거 형. 필요한 경우 문자열. 현재 사용자에게는 역할이 하나만 있지만 변경 될 수 있음)
높은 수준의 문제 : 위의 데이터베이스 구조를 감안할 때 다음을 수행 할 수 있습니다.
- 양식 인증을 사용한 단순 로그인
- 내 작업을 [Authorize (Roles = {MyRoles.Admin, MyRoles.Member})]로 장식합니다.
- 내 뷰에서 역할 사용 (일부 부분에 표시 할 링크 결정)
현재 내가 확신하는 것은 인증 방법뿐입니다. 그 후 나는 길을 잃었다. 어느 시점에서 사용자 역할 (로그인, 모든 권한 부여?)을 가져와야하는지 잘 모르겠습니다. 내 역할이 문자열이 아닐 수 있기 때문에 User.IsInRole ()과 어떻게 어울릴 지 잘 모르겠습니다.
이제 내가 필요한 것을 "간단한"성취를 찾지 못했기 때문에 여기서 묻습니다. 여러 예를 보았습니다.
인증의 경우 :
- 데이터베이스와 "SetAuthCookie"를 확인하는 간단한 사용자 유효성 검사가 있습니다.
- 또는 멤버 자격 공급자를 재정의하고 ValidateUser 내에서이 작업을 수행합니다.이 중 하나에서 간단한 사용자 역할을 지정하는 방법을 잘 모르겠습니다. HttpContext.Current.User.IsInRole ( "Administrator") 또한 열거 형 값과 함께 작동하도록 수정하는 방법을 모르겠습니다.
승인의 경우 다음을 확인했습니다.
- AuthorizeAttribute를 파생하고 AuthorizeCore 또는 OnAuthorization을 구현하여 역할을 처리합니까?
- IPrincipal 구현?
도움을 주시면 대단히 감사하겠습니다. 그러나 내가 Google에서 검색 한 내용 중 내가해야 할 일에 맞지 않는 것 같기 때문에 많은 세부 정보가 필요할 수 있습니다.
AuthorizeAttribute
문자열이 아닌 열거 형을 사용할 수 있는 사용자 지정 을 작성하십시오 . 권한을 부여해야 할 때 열거 형 유형 이름 + 열거 형 값을 추가하여 열거 형을 문자열로 변환하고 IsInRole
거기에서 사용하십시오 .
권한이있는 사용자에게 역할을 추가하려면 http://www.eggheadcafe.com/articles/20020906.aspHttpApplication
AuthenticateRequest
의 첫 번째 코드와 같은 이벤트 에 첨부해야합니다 (그러나 대규모 중첩 if 문을 guard 절로 반전!).
양식 인증 쿠키에서 사용자 역할을 왕복하거나 매번 데이터베이스에서 가져올 수 있습니다.
비슷한 것을 구현했다고 생각합니다. NerdDinner tutorial을
기반으로 한 내 솔루션 은 다음과 같습니다.
사용자를에 로그인 할 때 다음 과 같은 코드를 추가합니다.
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 ()
추가 질문이 있으면 알려주십시오.
나는 다음과 같이했다.
- Global.asax.cs를 사용하여 세션, 캐시 또는 응용 프로그램 상태에서 비교할 역할을로드하거나 ValidateUser 컨트롤러에서 즉석에서로드합니다.
컨트롤러에 [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
Use the built in Stored Procs to manipulate those tables. Then all you have to do is add the attribute.
For example you can have an "Admin" attribute on a view that selects a user and adds them to a role. You can use the stored proc to add that user to the role.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using SISWEBBSI.Models.Model;
using SISWEBBSI.Models.Model.Entities;
using SISWEBBSI.Models.ViewModel;
namespace SISWEBBSI.Controllers.ActionFilter
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public sealed class RequerAutorizacao : ActionFilterAttribute
{
public Grupo.Papeis[] Papeis = {} ;
public string ViewName { get; set; }
public ViewDataDictionary ViewDataDictionary { get; set; }
public AcessoNegadoViewModel AcessoNegadoViewModel { get; set; }
public override void OnActionExecuting(ActionExecutingContext FilterContext)
{
if (!FilterContext.HttpContext.User.Identity.IsAuthenticated)
{
string UrlSucesso = FilterContext.HttpContext.Request.Url.AbsolutePath;
string UrlRedirecionar = string.Format("?ReturnUrl={0}", UrlSucesso);
string UrlLogin = FormsAuthentication.LoginUrl + UrlRedirecionar;
FilterContext.HttpContext.Response.Redirect(UrlLogin, true);
}
else
{
if (Papeis.Length > 0)
{
//Papel ADMINISTRADOR sempre terá acesso quando alguma restrição de papeis for colocada.
int NovoTamanho = Papeis.Count() + 1;
Array.Resize(ref Papeis, NovoTamanho);
Papeis[NovoTamanho - 1] = Grupo.Papeis.ADMINISTRADOR;
UsuarioModel Model = new UsuarioModel();
if (!Model.UsuarioExecutaPapel(FilterContext.HttpContext.User.Identity.Name, Papeis))
{
ViewName = "AcessoNegado";
String Mensagem = "Você não possui privilégios suficientes para essa operação. Você deve estar nos grupos que possuem";
if(Papeis.Length == 1)
{
Mensagem = Mensagem + " o papel: <BR/>";
}
else if (Papeis.Length > 1)
{
Mensagem = Mensagem + " os papéis: <BR/>";
}
foreach (var papel in Papeis)
{
Mensagem = Mensagem + papel.ToString() + "<br/>";
}
AcessoNegadoViewModel = new AcessoNegadoViewModel();
AcessoNegadoViewModel.Mensagem = Mensagem;
ViewDataDictionary = new ViewDataDictionary(AcessoNegadoViewModel);
FilterContext.Result = new ViewResult { ViewName = ViewName, ViewData = ViewDataDictionary };
return;
}
}
}
}
}
}
ReferenceURL : https://stackoverflow.com/questions/1385042/asp-net-mvc-forms-authentication-authorize-attribute-simple-roles
'programing' 카테고리의 다른 글
모든 사용자 및 그룹 목록 (0) | 2021.01.18 |
---|---|
Django, ModelChoiceField () 및 초기 값 (0) | 2021.01.18 |
JS : 문자열의 경로에서 파일 이름을 제거하는 가장 최적화 된 방법은 무엇입니까? (0) | 2021.01.18 |
모든 쿼리 문자열 이름 / 값 쌍을 컬렉션으로 가져 오는 방법이 있습니까? (0) | 2021.01.18 |
C # 4.0 : 기본값이있는 선택적 매개 변수로 Color를 사용할 수 있습니까? (0) | 2021.01.18 |