ASP.NET MVC #18
نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۰۱/۳۱ ۱۰:۴۵:۰۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
public string Roles { get; set; } // comma-separated list of role names
public string Users { get; set; } // comma-separated list of usernames
[Authorize(Roles="Admins")]
public class AdminController : Controller
{
[Authorize(Users="Vahid")]
public ActionResult DoSomethingSecure()
{
}
}
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<!-- we don't want to stop anyone seeing the css and images -->
<location path="Content">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
<location path="secure">
<system.web>
<authorization>
<allow roles="Administrators" />
<deny users="*" />
</authorization>
</system.web>
</location>
[System.Web.Mvc.AllowAnonymous]
public ActionResult Login()
{
return View();
}
public class LogonAuthorize : AuthorizeAttribute {
public override void OnAuthorization(AuthorizationContext filterContext) {
if (!(filterContext.Controller is AccountController))
base.OnAuthorization(filterContext);
}
}
using System.Web.Mvc;
namespace MvcApplication15.Controllers
{
public class HomeController : Controller
{
[Authorize]
public ActionResult Index()
{
return View();
}
}
}
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
Current user: @User.Identity.Name
<authentication mode="Windows" />
<authentication mode="Forms">
<!--one month ticket-->
<forms name=".403MyApp"
cookieless="UseCookies"
loginUrl="~/Account/LogOn"
defaultUrl="~/Home"
slidingExpiration="true"
protection="All"
path="/"
timeout="43200"/>
</authentication>
using System.ComponentModel.DataAnnotations;
namespace MvcApplication15.Models
{
public class Account
{
[Required(ErrorMessage = "Username is required to login.")]
[StringLength(20)]
public string Username { get; set; }
[Required(ErrorMessage = "Password is required to login.")]
[DataType(DataType.Password)]
public string Password { get; set; }
public bool RememberMe { get; set; }
}
}
using System.Web.Mvc;
using MvcApplication15.Models;
namespace MvcApplication15.Controllers
{
public class AccountController : Controller
{
[HttpGet]
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(Account loginInfo, string returnUrl)
{
return View();
}
}
}
http://localhost/Account/LogOn?ReturnUrl=something
using System.Web.Mvc;
using System.Web.Security;
using MvcApplication15.Models;
namespace MvcApplication15.Controllers
{
public class AccountController : Controller
{
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
if (User.Identity.IsAuthenticated) //remember me
{
if (shouldRedirect(returnUrl))
{
return Redirect(returnUrl);
}
return Redirect(FormsAuthentication.DefaultUrl);
}
return View(); // show the login page
}
[HttpGet]
public void LogOut()
{
FormsAuthentication.SignOut();
}
private bool shouldRedirect(string returnUrl)
{
// it's a security check
return !string.IsNullOrWhiteSpace(returnUrl) &&
Url.IsLocalUrl(returnUrl) &&
returnUrl.Length > 1 &&
returnUrl.StartsWith("/") &&
!returnUrl.StartsWith("//") &&
!returnUrl.StartsWith("/\\");
}
[HttpPost]
public ActionResult LogOn(Account loginInfo, string returnUrl)
{
if (this.ModelState.IsValid)
{
if (loginInfo.Username == "Vahid" && loginInfo.Password == "123")
{
FormsAuthentication.SetAuthCookie(loginInfo.Username, loginInfo.RememberMe);
if (shouldRedirect(returnUrl))
{
return Redirect(returnUrl);
}
FormsAuthentication.RedirectFromLoginPage(loginInfo.Username, loginInfo.RememberMe);
}
}
this.ModelState.AddModelError("", "The user name or password provided is incorrect.");
ViewBag.Error = "Login faild! Make sure you have entered the right user name and password!";
return View(loginInfo);
}
}
}
[Authorize(Users="Vahid")]
using System;
using System.Web.Security;
namespace MvcApplication15.Helper
{
public class CustomRoleProvider : RoleProvider
{
public override bool IsUserInRole(string username, string roleName)
{
if (username.ToLowerInvariant() == "ali" && roleName.ToLowerInvariant() == "User")
return true;
// blabla ...
return false;
}
public override string[] GetRolesForUser(string username)
{
if (username.ToLowerInvariant() == "ali")
{
return new[] { "User", "Helpdesk" };
}
if(username.ToLowerInvariant()=="vahid")
{
return new [] { "Admin" };
}
return new string[] { };
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override string ApplicationName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
throw new NotImplementedException();
}
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
}
}
<roleManager>
<providers>
<clear />
<add name="CustomRoleProvider" type="MvcApplication15.Helper.CustomRoleProvider"/>
</providers>
</roleManager>
[Authorize(Roles = "Admin")]
public class HomeController : Controller
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
if (User.Identity.IsAuthenticated) //remember me
{
if (ShouldRedirect(returnUrl))
{
return Redirect(returnUrl);
}
return Redirect(FormsAuthentication.DefaultUrl);
}
return View(); // show the login page
}
[Authorize(Roles = "Admin")]
IsAuthenticated=true
ShouldRedirect(returnUrl)
<roleManager cacheRolesInCookie="true" defaultProvider="CustomRoleProvider" enabled="true"> <providers> <clear /> <add name="CustomRoleProvider" type="MvcApplication.Lib.CustomRoleProvider" /> </providers> </roleManager>
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new HttpStatusCodeResult(403);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
using System;
using System.Web.Mvc;
namespace SecurityModule
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class SiteAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
throw new UnauthorizedAccessException(); //to avoid multiple redirects
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
}
public class CustomRoleProvider : System.Web.Security.RoleProvider
{
public override bool IsUserInRole(string username, string roleName)
{
//if (username.ToLowerInvariant() == "ali" && roleName.ToLowerInvariant() == "User")
// return true;
// blabla ...
return true;
}
public override string[] GetRolesForUser(string username)
{
using (var context = new PublishingContext())
{
var user = context.Users.Where(x => x.Username == username).FirstOrDefault();
var roles = from ur in user.Roles
from r in context.Roles
where ur.Id == r.Id
select r.Role; //نام نقش
if (roles != null)
{
return roles.ToArray();
}
}
return new string[] {};
}
}
public class CustomRoleProvider : RoleProvider
{
public override bool IsUserInRole(string username, string roleName)
{
var rolesService = ObjectFactory.GetInstance<IRolesService>();
return rolesService.IsUserInRole(username, roleName);
}
//...
}
public class EfRole : EfGenericService<Role>, IRole
{
public EfRole(IUnitOfWork uow) : base(uow)
{
}
public bool IsUserInRole(string username, string roleName)
{
using (var context = new PublishingContext())
{
var user = context.Users.Where(x => x.Username.Equals(username, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
var roles = from ur in user.Rolls
from r in context.Rolls
where ur.Id == r.Id
select r.Rol;
if (user != null)
return roles.Any(x => x.Equals(roleName, StringComparison.CurrentCultureIgnoreCase));
else
return false;
}
}
}
public interface IRoleService
{
bool IsUserInRole(string username, string roleName);
string[] GetRolesForUser(string username);
void AddUsersToRoles(string[] usernames, string[] roleNames);
string ApplicationName { get; set; }
void CreateRole(string roleName);
bool DeleteRole(string roleName, bool throwOnPopulatedRole);
string[] FindUsersInRole(string roleName, string usernameToMatch);
string[] GetAllRoles();
string[] GetUsersInRole(string roleName);
void RemoveUsersFromRoles(string[] usernames, string[] roleNames);
bool RoleExists(string roleName);
} public class RoleService: IRoleService
{
private readonly IDbSet<Role> _role;
private readonly IUnitOfWork _uow;
public RoleService(IUnitOfWork uow)
{
_uow = uow;
_role = uow.Set<Role>();
}
public bool IsUserInRole(string username, string roleName)
{
throw new NotImplementedException();
}
public string[] GetRolesForUser(string username)
{
throw new NotImplementedException();
}
//...
} public class EfRolesService : IRolesService
{
readonly IUnitOfWork _uow;
readonly IDbSet<Role> _roles;
public EfRolesService(IUnitOfWork uow)
{
_uow = uow;
_roles = _uow.Set<Role>();
}
public IList<Role> FindUserRoles(int userId)
{
var query = from role in _roles
from user in role.Users
where user.Id == userId
select role;
return query.OrderBy(x => x.Name).ToList();
}
public string[] GetRolesForUser(int userId)
{
var roles = FindUserRoles(userId);
if (roles == null || !roles.Any())
{
return new string[] { };
}
return roles.Select(x => x.Name).ToArray();
}
public bool IsUserInRole(int userId, string roleName)
{
var query = from role in _roles
where role.Name == roleName
from user in role.Users
where user.Id == userId
select role;
var userRole = query.FirstOrDefault();
return userRole != null;
}
} public class CustomRoleProvider : RoleProvider
{
public override bool IsUserInRole(string username, string roleName)
{
// Since the role provider, in this case the CustomRoleProvider is instantiated by
// the ASP.NET framework the best solution is to use the service locator pattern.
// The service locator pattern is normally considered to be an anti-pattern but
// sometimes you have to be pragmatic and accept the limitation on the framework
// that is being used (in this case the ASP.NET framework).
var rolesService = ObjectFactory.GetInstance<IRolesService>();
return rolesService.IsUserInRole(username.ToInt(), roleName);
}
public override string[] GetRolesForUser(string username)
{
var rolesService = ObjectFactory.GetInstance<IRolesService>();
return rolesService.GetRolesForUser(username.ToInt());
}
// مابقی نیازی نیست پیاده سازی شوند public static int ToInt(this string data)
{
if (string.IsNullOrWhiteSpace(data)) return 0;
int result;
return int.TryParse(data, out result) ? result : 0;
} FormsAuthentication.SetAuthCookie(user.Id.ToString(CultureInfo.InvariantCulture), ... // ... FormsAuthentication.RedirectFromLoginPage(user.Id.ToString(CultureInfo.InvariantCulture), ...
FormsAuthentication.SetAuthCookie(user.Id.ToString(CultureInfo.InvariantCulture), user.RememberMe); FormsAuthentication.RedirectFromLoginPage(user.Id.ToString(CultureInfo.InvariantCulture), user.RememberMe);
<roleManager enabled="true" defaultProvider="CustomRoleProvider"
cacheRolesInCookie="true">
<providers>
<clear />
<add name="CustomRoleProvider"
type="MyApp.Web.Helper.CustomRoleProvider"/>
</providers>
</roleManager>
وقتی در فرم لاگین هم به صورت دستی Id رو ارسال میکنم، باز هم پیام Attempted to perform an unauthorized operation. دریافت میکنم. آیا تغییری دیگری در View لاگین نیاز هست اعمال بشه؟
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult LogOn(User user, string returnUrl)
{
if (this.ModelState.IsValid)
{
if (_userService.IsValid(user))
{
int userID = _userService.GetUser(u => u.Username == user.Username && u.Password == user.Password).Id;
FormsAuthentication.SetAuthCookie(userID.ToString(CultureInfo.InvariantCulture), user.RememberMe);
if (shouldRedirect(returnUrl))
{
return Redirect(returnUrl);
}
FormsAuthentication.RedirectFromLoginPage(userID.ToString(CultureInfo.InvariantCulture), user.RememberMe);
}
}
this.ModelState.AddModelError("", "The user name or password provided is incorrect.");
ViewBag.Error = "Login faild! Make sure you have entered the right user name and password!";
return View(user);
} <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear/>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
WebSecurity.CreateUserAndAccount(
model.UserName,
model.Password,
new { Mobile = model.Mobile },
false);
<location path="content">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
<authentication mode="forms">
<forms loginurl="~/account/logon" slidingexpiration="true" timeout="2"/>
</authentication>
<authorization>
<!--<allow roles="?"/>-->
<deny users="?"/>
</authorization>
// in RegisterRoutes -> Global.asax.cs
routes.IgnoreRoute("{*js}", new { js = @".*\.js(/.*)?"});
routes.IgnoreRoute("{*css}", new { css = @".*\.css(/.*)?"});
if (User.IsInRole("Admins"))
return Redirect("~/Admins/Default");
else if (User.IsInRole("Editors"))
return Redirect("~/Editors/Default");
else //...filterContext.ActionDescriptor.ControllerDescriptor.ControllerName filterContext.ActionDescriptor.ActionName
[AllowAnonymous]
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
}
[AllowAnonymous]
public class SecurityController : Controller
{
[HttpGet]
public ActionResult LogOn(string returnUrl)
{
if (User.Identity.IsAuthenticated) //remember me
{
if (CanRedirect(returnUrl))
{
return Redirect(returnUrl);
}
return Redirect(FormsAuthentication.DefaultUrl);
}
return View(); // show the login page
}
}<authorization>
<deny users="?" />
</authorization><authorization>
<deny users="?" />
</authorization> GlobalFilters.Filters.Add(new System.Web.Mvc.AuthorizeAttribute());
[HttpPost]
public virtual ActionResult LogOn(Accounts acc)
{
FormsAuthentication.SetAuthCookie(acc.Username, acc.RememberMe);
return View();
} public ActionResult DeleteMessage( int id )
{
_messageService.DeleteMessage(id , User.Identity.Name);
return RedirectToAction(MVC.User.SendMessages());
} public virtual ActionResult SendMessages()
{
string s = User.Identity.Name;// Error : Object reference not set to an instance of an object.
return View(_messageService.SendMessageListUser(User.Identity.Name));
} FormsAuthentication.SetAuthCookie(... // ... FormsAuthentication.RedirectFromLoginPage(...
[PrincipalPermissionAttribute(SecurityAction.Demand, Role = "MyRole")]
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
<roleManager cacheRolesInCookie="true" defaultProvider="CustomRoleProvider" enabled="true">
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateCaptchaAttribute]
[AllowAnonymous]
public virtual ActionResult Login(LoginWithCaptchaViewModel vm, string returnUrl)
{ [Authorize(Users = User.Identity.Name)] البته این کد جواب نمیدهد برای فهم کلام نوشتم
public void Init(HttpApplication application)
{
application.EndRequest += onEndRequest;
}
public void onEndRequest(Object sender, EventArgs e)
{
HttpCookieCollection cookies = (((HttpApplication)sender).Response).Cookies;
//todo: check Cookie.Value.Length FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // ticket version
admin.UserName, // authenticated username
DateTime.Now, // issueDate
DateTime.Now.AddMinutes(30), // expiryDate
true, // true to persist across browser sessions
"", // can be used to store additional user data
FormsAuthentication.FormsCookiePath); // the path for the cookie
// Encrypt the ticket using the machine key
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
// Add the cookie to the request to save it
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) {HttpOnly = true};
Response.Cookies.Add(cookie);