目录

1.  介绍

2.  UML

2.1  实体类UML图

2.2  业务相关UML图

3.  核心代码分析

3.1  实体类源代码

3.2  业务相关源代码

3.3  相关控制器源代码

3.4  相关View源代码

4.  总结


1.  介绍

1.1  nopcommerce介绍

nopcommerce是国外的一个高质量的开源b2c网站系统,基于EntityFramework4.0和MVC3.0,使用Razor模板引擎,有很强的插件机制,包括支付配送功能都是通过插件来实现的.

nopcommerce主要模块从上往下Nop.Web、Nop.Admin、Nop.Web.Framework、Nop插件、Nop.Services、Nop.Core、Nop.Data。引用的第三方模块EntityFramework,Autofac(控制反转,即依赖注入),telerik.extern.mvc(后台管理用的界面,2.0后开始使用)

1.2  文章来由

我之前对ASP.NET  MVC4的用户验证和权限管理这块内容理解的不深刻,一次偶然的机会使得我下载到了nopcommerce的源代码,该项目中含有访问控制功能,其功能页面如图1-1所示。

为了进一步理解MVC4的用户验证和权限管理的内容,我用了两天时间窥视了nopcommerce的访问控制功能,略有心得体会,并以我自己的理解内容写了一个Demo:AclDemo,该项目将在下一篇分析以及提供源代码。

图1-1

2.  UML

该小节主要提供了nopcommerce项目中的访问控制功能的UML类图以及类图说明,在制作UML类图的过程中,我简化了UML类图,这样是为了让UML内容不冗余。简化后的UML类图只显示了和访问控制功能有关的内容。

2.1  实体类UML图

2.2  业务相关UML图

3.  核心代码分析

3.1  实体类源代码

  Customer类
  

 /// <summary>     /// Represents a customer role     /// </summary>     public partial class CustomerRole : BaseEntity     {         private ICollection<PermissionRecord> _permissionRecords;         /// <summary>         /// Gets or sets the customer role name         /// </summary>         public string Name { get; set; }         /// <summary>         /// Gets or sets a value indicating whether the customer role is active         /// </summary>         public bool Active { get; set; }         /// <summary>         /// Gets or sets a value indicating whether the customer role is system         /// </summary>         public bool IsSystemRole { get; set; }         /// <summary>         /// Gets or sets the customer role system name         /// </summary>         public string SystemName { get; set; }        /// <summary>         /// Gets or sets the permission records         /// </summary>         public virtual ICollection<PermissionRecord> PermissionRecords         {             get { return _permissionRecords ?? (_permissionRecords = new List<PermissionRecord>()); }             protected set { _permissionRecords = value; }         }     }

CustomerRole类

  

 /// <summary>     /// Represents a permission record     /// </summary>     public partial class PermissionRecord : BaseEntity     {         private ICollection<CustomerRole> _customerRoles;         /// <summary>         /// Gets or sets the permission name         /// </summary>         public string Name { get; set; }         /// <summary>         /// Gets or sets the permission system name         /// </summary>         public string SystemName { get; set; }                  /// <summary>         /// Gets or sets the permission category         /// </summary>         public string Category { get; set; }                  /// <summary>         /// Gets or sets discount usage history         /// </summary>         public virtual ICollection<CustomerRole> CustomerRoles         {             get { return _customerRoles ?? (_customerRoles = new List<CustomerRole>()); }             protected set { _customerRoles = value; }         }        }

PermissionRecord类

3.2  业务相关源代码

  /// <summary>     /// Customer service interface     /// </summary>     public partial interface ICustomerService     {         #region Customers         /// <summary>         /// Get customer by username         /// </summary>         /// <param name="username">Username</param>         /// <returns>Customer</returns>         Customer GetCustomerByUsername(string username);         #endregion     }
    

ICustomerService接口

 /// <summary>     /// Customer service     /// </summary>     public partial class CustomerService : ICustomerService     {         #region Constants         #endregion         #region Fields         private readonly IRepository<Customer> _customerRepository;         private readonly IRepository<CustomerRole> _customerRoleRepository;         #endregion         #region Ctor         public CustomerService(             IRepository<Customer> customerRepository,             IRepository<CustomerRole> customerRoleRepository,)         {             this._customerRepository = customerRepository;             this._customerRoleRepository = customerRoleRepository;         }         #endregion         #region Methods         #region Customers                  /// <summary>         /// Get customer by username         /// </summary>         /// <param name="username">Username</param>         /// <returns>Customer</returns>         public virtual Customer GetCustomerByUsername(string username)         {             if (string.IsNullOrWhiteSpace(username))                 return null;             var query = from c in _customerRepository.Table                         orderby c.Id                         where c.Username == username                         select c;             var customer = query.FirstOrDefault();             return customer;         }                  #endregion                  #endregion     }

CustomerService类

 public partial interface IAuthenticationService      {         void SignIn(Customer customer, bool createPersistentCookie);         void SignOut();         Customer GetAuthenticatedCustomer();     }

IAuthenticationService接口

 public partial class FormsAuthenticationService : IAuthenticationService     {         private readonly HttpContextBase _httpContext;         private readonly ICustomerService _customerService;         private readonly CustomerSettings _customerSettings;         private readonly TimeSpan _expirationTimeSpan;         private Customer _cachedCustomer;         /// <summary>         /// Ctor         /// </summary>         /// <param name="httpContext">HTTP context</param>         /// <param name="customerService">Customer service</param>         /// <param name="customerSettings">Customer settings</param>         public FormsAuthenticationService(HttpContextBase httpContext,             ICustomerService customerService, CustomerSettings customerSettings)         {             this._httpContext = httpContext;             this._customerService = customerService;             this._customerSettings = customerSettings;             this._expirationTimeSpan = FormsAuthentication.Timeout;         }         public virtual void SignIn(Customer customer, bool createPersistentCookie)         {             var now = DateTime.UtcNow.ToLocalTime();             var ticket = new FormsAuthenticationTicket(                 1 /*version*/,                 _customerSettings.UsernamesEnabled ? customer.Username : customer.Email,                 now,                 now.Add(_expirationTimeSpan),                 createPersistentCookie,                 _customerSettings.UsernamesEnabled ? customer.Username : customer.Email,                 FormsAuthentication.FormsCookiePath);             var encryptedTicket = FormsAuthentication.Encrypt(ticket);             var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);             cookie.HttpOnly = true;             if (ticket.IsPersistent)             {                 cookie.Expires = ticket.Expiration;             }             cookie.Secure = FormsAuthentication.RequireSSL;             cookie.Path = FormsAuthentication.FormsCookiePath;             if (FormsAuthentication.CookieDomain != null)             {                 cookie.Domain = FormsAuthentication.CookieDomain;             }             _httpContext.Response.Cookies.Add(cookie);             _cachedCustomer = customer;         }         public virtual void SignOut()         {             _cachedCustomer = null;             FormsAuthentication.SignOut();         }         public virtual Customer GetAuthenticatedCustomer()         {             if (_cachedCustomer != null)                 return _cachedCustomer;             if (_httpContext == null ||                 _httpContext.Request == null ||                 !_httpContext.Request.IsAuthenticated ||                 !(_httpContext.User.Identity is FormsIdentity))             {                 return null;             }             var formsIdentity = (FormsIdentity)_httpContext.User.Identity;             var customer = GetAuthenticatedCustomerFromTicket(formsIdentity.Ticket);             if (customer != null && customer.Active && !customer.Deleted && customer.IsRegistered())                 _cachedCustomer = customer;             return _cachedCustomer;         }         public virtual Customer GetAuthenticatedCustomerFromTicket(FormsAuthenticationTicket ticket)         {             if (ticket == null)                 throw new ArgumentNullException("ticket");             var usernameOrEmail = ticket.UserData;             if (String.IsNullOrWhiteSpace(usernameOrEmail))                 return null;             var customer = _customerSettings.UsernamesEnabled                 ? _customerService.GetCustomerByUsername(usernameOrEmail)                 : _customerService.GetCustomerByEmail(usernameOrEmail);             return customer;         }     }

FormsAuthenticationService类

    FormsAuthenticationService类实现代码分析

SignOut方法比较简单,主要是调用了FormsAuthentication的退出方法。重点介绍SignIn()和GetAuthenticatedCustomer()方法

在SignIn()方法中,首先创建一个类型为FormsAuthenticationTicket的ticket,并且将该ticket进行加密,然后将加密后的信息保存到cookie。

在GetAuthenticatedCustomer()中,如果说已经缓存了当前用户,则直接返回,如果说当前http上下文没有使用Forms验证的话或者验证不存在的话,则直接返回空置。紧接着,获取之前已经保存的ticket,取到ticket之后,根据保存的UserData,获取到已经登录用户的信息。

  

 public enum CustomerLoginResults     {         /// <summary>         /// Login successful         /// </summary>         Successful = 1,         /// <summary>         /// Customer dies not exist (email or username)         /// </summary>         CustomerNotExist = 2,         /// <summary>         /// Wrong password         /// </summary>         WrongPassword = 3,         /// <summary>         /// Account have not been activated         /// </summary>         NotActive = 4,         /// <summary>         /// Customer has been deleted          /// </summary>         Deleted = 5,         /// <summary>         /// Customer not registered          /// </summary>         NotRegistered = 6,     }

CustomerLoginResults枚举类型

  

 public partial interface ICustomerRegistrationService     {         /// <summary>         /// Validate customer         /// </summary>         /// <param name="usernameOrEmail">Username or email</param>         /// <param name="password">Password</param>         /// <returns>Result</returns>         CustomerLoginResults ValidateCustomer(string usernameOrEmail, string password);     }

ICustomerRegistrationService接口

  

  public partial class CustomerRegistrationService : ICustomerRegistrationService     {         #region Fields         private readonly ICustomerService _customerService;         private readonly CustomerSettings _customerSettings;         #endregion         #region Ctor         /// <summary>         /// Ctor         /// </summary>         /// <param name="customerService">Customer service</param>         /// <param name="encryptionService">Encryption service</param>         /// <param name="newsLetterSubscriptionService">Newsletter subscription service</param>         /// <param name="localizationService">Localization service</param>         /// <param name="storeService">Store service</param>         /// <param name="rewardPointsSettings">Reward points settings</param>         /// <param name="customerSettings">Customer settings</param>         public CustomerRegistrationService(ICustomerService customerService,              CustomerSettings customerSettings)         {             this._customerService = customerService;             this._customerSettings = customerSettings;         }         #endregion         #region Methods         /// <summary>         /// Validate customer         /// </summary>         /// <param name="usernameOrEmail">Username or email</param>         /// <param name="password">Password</param>         /// <returns>Result</returns>         public virtual CustomerLoginResults ValidateCustomer(string usernameOrEmail, string password)         {             Customer customer;             if (_customerSettings.UsernamesEnabled)                 customer = _customerService.GetCustomerByUsername(usernameOrEmail);             else                 customer = _customerService.GetCustomerByEmail(usernameOrEmail);             if (customer == null)                 return CustomerLoginResults.CustomerNotExist;             string pwd = "";             bool isValid = pwd == customer.Password;             if (!isValid)                 return CustomerLoginResults.WrongPassword;             //save last login date             customer.LastLoginDateUtc = DateTime.UtcNow;             _customerService.UpdateCustomer(customer);             return CustomerLoginResults.Successful;         }         #endregion     }

CustomerRegistrationService

  CustomerRegistrationService类实现代码分析

在验证用户的方法中还是比较简单的,首先根据用户用户设置,是用户名登录还是邮箱登录,然后根据用户名或者邮箱获取到用户信息,如果用户信息为空的话,则表示用户不存在,否则,则更新登录用户的用户信息。

    nopcommerce项目中实现的用户验证绝非如此简单,它提供了密码加密格式的验证,感兴趣的同学可以下载看一看。

  

 /// <summary>     /// Work context     /// </summary>     public interface IWorkContext     {         /// <summary>         /// Gets or sets the current customer         /// </summary>         Customer CurrentCustomer { get; set; }                  /// <summary>         /// Get or set value indicating whether we're in admin area         /// </summary>         bool IsAdmin { get; set; }     }

IWorkContext接口:该接口主要是提供当前工作环境的信息,比如当前用户信息、当前语言等等,简化版中只提供了当前用户信息

  

 public partial class WebWorkContext : IWorkContext     {         #region Const         private const string CustomerCookieName = "Nop.customer";         #endregion         #region Fields         private readonly HttpContextBase _httpContext;         private readonly ICustomerService _customerService;         private readonly IAuthenticationService _authenticationService;         private Customer _cachedCustomer;         #endregion         #region Ctor         public WebWorkContext(HttpContextBase httpContext,             ICustomerService customerService,             IAuthenticationService authenticationService,)         {             this._httpContext = httpContext;             this._customerService = customerService;             this._authenticationService = authenticationService;         }         #endregion         #region Utilities         protected virtual HttpCookie GetCustomerCookie()         {             if (_httpContext == null || _httpContext.Request == null)                 return null;             return _httpContext.Request.Cookies[CustomerCookieName];         }         protected virtual void SetCustomerCookie(Guid customerGuid)         {             if (_httpContext != null && _httpContext.Response != null)             {                 var cookie = new HttpCookie(CustomerCookieName);                 cookie.HttpOnly = true;                 cookie.Value = customerGuid.ToString();                 if (customerGuid == Guid.Empty)                 {                     cookie.Expires = DateTime.Now.AddMonths(-1);                 }                 else                 {                     int cookieExpires = 24*365; //TODO make configurable                     cookie.Expires = DateTime.Now.AddHours(cookieExpires);                 }                 _httpContext.Response.Cookies.Remove(CustomerCookieName);                 _httpContext.Response.Cookies.Add(cookie);             }         }                #endregion         #region Properties         /// <summary>         /// Gets or sets the current customer         /// </summary>         public virtual Customer CurrentCustomer         {             get             {                 if (_cachedCustomer != null)                     return _cachedCustomer;                 Customer customer = null;                                  //registered user                 if (customer == null || customer.Deleted || !customer.Active)                 {                     customer = _authenticationService.GetAuthenticatedCustomer();                 }                 //impersonate user if required (currently used for 'phone order' support)                 if (customer != null && !customer.Deleted && customer.Active)                 {                     var impersonatedCustomerId = customer.GetAttribute<int?>(SystemCustomerAttributeNames.ImpersonatedCustomerId);                     if (impersonatedCustomerId.HasValue && impersonatedCustomerId.Value > 0)                     {                         var impersonatedCustomer = _customerService.GetCustomerById(impersonatedCustomerId.Value);                         if (impersonatedCustomer != null && !impersonatedCustomer.Deleted && impersonatedCustomer.Active)                         {                             //set impersonated customer                             _originalCustomerIfImpersonated = customer;                             customer = impersonatedCustomer;                         }                     }                 }                 //load guest customer                 if (customer == null || customer.Deleted || !customer.Active)                 {                     var customerCookie = GetCustomerCookie();                     if (customerCookie != null && !String.IsNullOrEmpty(customerCookie.Value))                     {                         Guid customerGuid;                         if (Guid.TryParse(customerCookie.Value, out customerGuid))                         {                             var customerByCookie = _customerService.GetCustomerByGuid(customerGuid);                             if (customerByCookie != null &&                                 //this customer (from cookie) should not be registered                                 !customerByCookie.IsRegistered())                                 customer = customerByCookie;                         }                     }                 }                 //create guest if not exists                 if (customer == null || customer.Deleted || !customer.Active)                 {                     customer = _customerService.InsertGuestCustomer();                 }                 //validation                 if (!customer.Deleted && customer.Active)                 {                     SetCustomerCookie(customer.CustomerGuid);                     _cachedCustomer = customer;                 }                 return _cachedCustomer;             }             set             {                 SetCustomerCookie(value.CustomerGuid);                 _cachedCustomer = value;             }         }         /// <summary>         /// Get or set value indicating whether we're in admin area         /// </summary>         public virtual bool IsAdmin { get; set; }         #endregion     }

WebWorkContext类:该类实现了IWorkContext接口,提供了web下的工作环境

  WebWorkContext类实现代码分析

该类的CurrentCustomer属性的实现简化了一部分,我们首先判断用户信息是否已经缓存,如果已经缓存了,则直接返回,如果没有,则需要从FormsAuthenticationService中重新获取用户信息,根据该用户的信息,设置单个用户的cookie。更加详细的实现内容请下载nopcommerce源码。

  

 /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permission">Permission record</param>         /// <returns>true - authorized; otherwise, false</returns>         bool Authorize(PermissionRecord permission);         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permission">Permission record</param>         /// <param name="customer">Customer</param>         /// <returns>true - authorized; otherwise, false</returns>         bool Authorize(PermissionRecord permission, Customer customer);         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permissionRecordSystemName">Permission record system name</param>         /// <returns>true - authorized; otherwise, false</returns>         bool Authorize(string permissionRecordSystemName);         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permissionRecordSystemName">Permission record system name</param>         /// <param name="customer">Customer</param>         /// <returns>true - authorized; otherwise, false</returns>         bool Authorize(string permissionRecordSystemName, Customer customer);

IPermissionService接口

  

 public partial class PermissionService : IPermissionService     {         #region Constants         /// <summary>         /// Key pattern to clear cache         /// </summary>         private const string PERMISSIONS_PATTERN_KEY = "Nop.permission.";         #endregion         #region Fields         private readonly IRepository<PermissionRecord> _permissionRecordRepository;         private readonly ICustomerService _customerService;         private readonly IWorkContext _workContext;         #endregion         #region Ctor         /// <summary>         /// Ctor         /// </summary>         /// <param name="permissionRecordRepository">Permission repository</param>         /// <param name="customerService">Customer service</param>         /// <param name="workContext">Work context</param>         /// <param name="localizationService">Localization service</param>         /// <param name="languageService">Language service</param>         /// <param name="cacheManager">Cache manager</param>         public PermissionService(IRepository<PermissionRecord> permissionRecordRepository,             ICustomerService customerService,             IWorkContext workContext)         {             this._permissionRecordRepository = permissionRecordRepository;             this._customerService = customerService;             this._workContext = workContext;         }         #endregion         #region Methods         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permission">Permission record</param>         /// <returns>true - authorized; otherwise, false</returns>         public virtual bool Authorize(PermissionRecord permission)         {             return Authorize(permission, _workContext.CurrentCustomer);         }         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permission">Permission record</param>         /// <param name="customer">Customer</param>         /// <returns>true - authorized; otherwise, false</returns>         public virtual bool Authorize(PermissionRecord permission, Customer customer)         {             if (permission == null)                 return false;             if (customer == null)                 return false;             //old implementation of Authorize method             //var customerRoles = customer.CustomerRoles.Where(cr => cr.Active);             //foreach (var role in customerRoles)             //    foreach (var permission1 in role.PermissionRecords)             //        if (permission1.SystemName.Equals(permission.SystemName, StringComparison.InvariantCultureIgnoreCase))             //            return true;             //return false;             return Authorize(permission.SystemName, customer);         }         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permissionRecordSystemName">Permission record system name</param>         /// <returns>true - authorized; otherwise, false</returns>         public virtual bool Authorize(string permissionRecordSystemName)         {             return Authorize(permissionRecordSystemName, _workContext.CurrentCustomer);         }         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permissionRecordSystemName">Permission record system name</param>         /// <param name="customer">Customer</param>         /// <returns>true - authorized; otherwise, false</returns>         public virtual bool Authorize(string permissionRecordSystemName, Customer customer)         {             if (String.IsNullOrEmpty(permissionRecordSystemName))                 return false;             var customerRoles = customer.CustomerRoles.Where(cr => cr.Active);             foreach (var role in customerRoles)                 if (Authorize(permissionRecordSystemName, role))                     //yes, we have such permission                     return true;                          //no permission found             return false;         }         #endregion         #region Utilities         /// <summary>         /// Authorize permission         /// </summary>         /// <param name="permissionRecordSystemName">Permission record system name</param>         /// <param name="customerRole">Customer role</param>         /// <returns>true - authorized; otherwise, false</returns>         protected virtual bool Authorize(string permissionRecordSystemName, CustomerRole customerRole)         {             if (String.IsNullOrEmpty(permissionRecordSystemName))                 return false;             string key = string.Format(PERMISSIONS_ALLOWED_KEY, customerRole.Id, permissionRecordSystemName);             return _cacheManager.Get(key, () =>             {                 foreach (var permission1 in customerRole.PermissionRecords)                     if (permission1.SystemName.Equals(permissionRecordSystemName, StringComparison.InvariantCultureIgnoreCase))                         return true;                 return false;             });         }         #endregion     }

PermissionService类实现代码分析

  PermissionService类实现代码分析

分析Authorize代码可以知道,首先是要获取当前用户所隶属的所有用户组,然后根据权限名称和用户组判断是否具有某个模块的访问权限。

3.3  相关控制器源代码

PermissionController类:主要是两个登录的Action,通过一下代码可以看出,当用户登录成功之后,需要调用 _authenticationService的登录方法,通过该方法记录已经登录用户的ID

 
 [NopHttpsRequirement(SslRequirement.Yes)]         public ActionResult Login(bool? checkoutAsGuest)         {             var model = new LoginModel();             model.UsernamesEnabled = _customerSettings.UsernamesEnabled;             model.CheckoutAsGuest = checkoutAsGuest.GetValueOrDefault();             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage;             return View(model);         }         [HttpPost]         [CaptchaValidator]         public ActionResult Login(LoginModel model, string returnUrl, bool captchaValid)         {             //validate CAPTCHA             if (_captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage && !captchaValid)             {                 ModelState.AddModelError("", _localizationService.GetResource("Common.WrongCaptcha"));             }             if (ModelState.IsValid)             {                 if (_customerSettings.UsernamesEnabled && model.Username != null)                 {                     model.Username = model.Username.Trim();                 }                 var loginResult = _customerRegistrationService.ValidateCustomer(_customerSettings.UsernamesEnabled ? model.Username : model.Email, model.Password);                 switch (loginResult)                 {                     case CustomerLoginResults.Successful:                         {                             var customer = _customerSettings.UsernamesEnabled ? _customerService.GetCustomerByUsername(model.Username) : _customerService.GetCustomerByEmail(model.Email);                             //migrate shopping cart                             _shoppingCartService.MigrateShoppingCart(_workContext.CurrentCustomer, customer, true);                             //sign in new customer                             _authenticationService.SignIn(customer, model.RememberMe);                             //activity log                             _customerActivityService.InsertActivity("PublicStore.Login", _localizationService.GetResource("ActivityLog.PublicStore.Login"), customer);                             if (String.IsNullOrEmpty(returnUrl) || !Url.IsLocalUrl(returnUrl))                                 return RedirectToRoute("HomePage");                                                          return Redirect(returnUrl);                         }                     case CustomerLoginResults.CustomerNotExist:                         ModelState.AddModelError("", _localizationService.GetResource("Account.Login.WrongCredentials.CustomerNotExist"));                         break;                     case CustomerLoginResults.Deleted:                         ModelState.AddModelError("", _localizationService.GetResource("Account.Login.WrongCredentials.Deleted"));                         break;                     case CustomerLoginResults.NotActive:                         ModelState.AddModelError("", _localizationService.GetResource("Account.Login.WrongCredentials.NotActive"));                         break;                     case CustomerLoginResults.NotRegistered:                         ModelState.AddModelError("", _localizationService.GetResource("Account.Login.WrongCredentials.NotRegistered"));                         break;                     case CustomerLoginResults.WrongPassword:                     default:                         ModelState.AddModelError("", _localizationService.GetResource("Account.Login.WrongCredentials"));                         break;                 }             }             //If we got this far, something failed, redisplay form             model.UsernamesEnabled = _customerSettings.UsernamesEnabled;             model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage;             return View(model);         }

SecurityController类:安全控制器,当用户权限不足时,则展示AccessDenied界面。Permissions是访问控制界面的Action

 /// <summary>
/// 拒绝访问
/// </summary>
/// <param name="pageUrl"></param>
/// <returns></returns>
public ActionResult AccessDenied(string pageUrl)
{
var currentCustomer = _workContext.CurrentCustomer;
if (currentCustomer == null || currentCustomer.IsGuest())
{
_logger.Information(string.Format("Access denied to anonymous request on {0}", pageUrl));
return View();
} _logger.Information(string.Format("Access denied to user #{0} '{1}' on {2}", currentCustomer.Email, currentCustomer.Email, pageUrl)); return View();
} /// <summary>
/// GET:/Admin/Security/Permissions
/// 获取权限列表
/// </summary>
/// <returns></returns>
public ActionResult Permissions()
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageAcl))
return AccessDeniedView(); var model = new PermissionMappingModel(); var permissionRecords = _permissionService.GetAllPermissionRecords();
var customerRoles = _customerService.GetAllCustomerRoles(true);
foreach (var pr in permissionRecords)
{
model.AvailablePermissions.Add(new PermissionRecordModel
{
//Name = pr.Name,
Name = pr.GetLocalizedPermissionName(_localizationService, _workContext),
SystemName = pr.SystemName
});
}
foreach (var cr in customerRoles)
{
model.AvailableCustomerRoles.Add(new CustomerRoleModel
{
Id = cr.Id,
Name = cr.Name
});
}
foreach (var pr in permissionRecords)
foreach (var cr in customerRoles)
{
bool allowed = pr.CustomerRoles.Count(x => x.Id == cr.Id) > ;
if (!model.Allowed.ContainsKey(pr.SystemName))
model.Allowed[pr.SystemName] = new Dictionary<int, bool>();
model.Allowed[pr.SystemName][cr.Id] = allowed;
} return View(model);
} /// <summary>
/// GET:/Admin/Security/Permissions
/// 提交访问权限
/// </summary>
/// <param name="form"></param>
/// <returns></returns>
[HttpPost, ActionName("Permissions")]
public ActionResult PermissionsSave(FormCollection form)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageAcl))
return AccessDeniedView(); var permissionRecords = _permissionService.GetAllPermissionRecords();
var customerRoles = _customerService.GetAllCustomerRoles(true); foreach (var cr in customerRoles)
{
string formKey = "allow_" + cr.Id;
var permissionRecordSystemNamesToRestrict = form[formKey] != null ? form[formKey].Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() : new List<string>(); foreach (var pr in permissionRecords)
{ bool allow = permissionRecordSystemNamesToRestrict.Contains(pr.SystemName);
if (allow)
{
if (pr.CustomerRoles.FirstOrDefault(x => x.Id == cr.Id) == null)
{
pr.CustomerRoles.Add(cr);
_permissionService.UpdatePermissionRecord(pr);
}
}
else
{
if (pr.CustomerRoles.FirstOrDefault(x => x.Id == cr.Id) != null)
{
pr.CustomerRoles.Remove(cr);
_permissionService.UpdatePermissionRecord(pr);
}
}
}
} SuccessNotification(_localizationService.GetResource("Admin.Configuration.ACL.Updated"));
return RedirectToAction("Permissions");
}

3.4  相关View源代码

PermissionMappingModel:访问控制管理界面模型

 public partial class PermissionMappingModel : BaseNopModel     {         public PermissionMappingModel()         {             AvailablePermissions = new List<PermissionRecordModel>();             AvailableCustomerRoles = new List<CustomerRoleModel>();             Allowed = new Dictionary<string, IDictionary<int, bool>>();         }         public IList<PermissionRecordModel> AvailablePermissions { get; set; }         public IList<CustomerRoleModel> AvailableCustomerRoles { get; set; }         //[permission system name] / [customer role id] / [allowed]         public IDictionary<string, IDictionary<int, bool>> Allowed { get; set; }     }

Permissions.cshtml:访问控制管理界面

 @model PermissionMappingModel
@{ //page title ViewBag.Title = T("Admin.Configuration.ACL").Text;
}
@using (Html.BeginForm())
{ @Html.AntiForgeryToken() <div class="section-header"> <div class="title"> <img src="@Url.Content("~/Administration/Content/images/ico-configuration.png")" alt="" /> @T("Admin.Configuration.ACL") </div> <div class="options"> <input type="submit" name="save" class="k-button" value="@T("Admin.Common.Save")" /> </div> </div> <table class="adminContent"> <tr> <td> @if (Model.AvailablePermissions.Count == 0) { <text>No permissions defined</text> } else if (Model.AvailableCustomerRoles.Count == 0) { <text>No customer roles available</text> } else { <script type="text/javascript"> $(document).ready(function () { @foreach (var cr in Model.AvailableCustomerRoles) { <text> $('#selectall-@(cr.Id)').click(function () { $('.allow_@(cr.Id)').attr('checked', $(this).is(':checked')).change(); }); </text> } }); </script> <table class="tablestyle" cellspacing="0" rules="all" border="1" style="width: 100%; border-collapse: collapse;"> <tbody> <tr class="headerstyle"> <th scope="col"> <strong>@T("Admin.Configuration.ACL.Permission")</strong> </th> @foreach (var cr in Model.AvailableCustomerRoles) { <th scope="col"> <strong>@cr.Name</strong> <input type="checkbox" id="selectall-@(cr.Id)" /> </th> } </tr> @{ bool altRow = true; } @foreach (var pr in Model.AvailablePermissions) { altRow = !altRow; <tr class="@(altRow ? "altrowstyle" : "rowstyle")"> <td> <span>@pr.Name</span> </td> @foreach (var cr in Model.AvailableCustomerRoles) { var allowed = Model.Allowed.ContainsKey(pr.SystemName) && Model.Allowed[pr.SystemName][cr.Id]; <td> <input class="allow_@(cr.Id)" class="allow_@(cr.Id)" type="checkbox" value="@(pr.SystemName)" name="allow_@(cr.Id)" @(allowed ? " checked=checked" : null) /> </td> } </tr> } </tbody> </table> } </td> </tr> </table> }

4.  总结

通过对nopcommerce项目中的访问控制代码的分析,使得我对MVC4下的用户验证的实现有了进一步的了解:通过FormsAuthentication和HttpCookie来进行用户验证以及具体的实现过程。

该项目中的访问控制也是值得学习的,使得权限记录和用户组发送多对多的关系,当能查询到某个用户组含有对应的访问权限,则表示该用户组对这个模块有访问权限。

通过学习nopcommerce项目代码,我也编写了一个小Demo:AclDemo,该项目将在下一篇进行分析和源代码下载,敬请期待,感兴趣的可以关注我。

NopCommerce源代码分析之用户验证和权限管理的更多相关文章

  1. MongoDB用户验证和权限管理

    官方参考页面: https://docs.mongodb.com/v3.6/tutorial/enable-authentication/ https://docs.mongodb.com/v3.6/ ...

  2. mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理

    1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理 3.mvc5+ef6+Bootstrap 项目心得--WebG ...

  3. [转]mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理

    本文转自:http://www.cnblogs.com/shootingstar/p/5629668.html 1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+B ...

  4. MySQL数据库(6)_用户操作与权限管理、视图、存储过程、触发器、基本函数

    用户操作与权限管理 MySQL用户操作 创建用户 方法一: CREATE USER语句创建 CREATE USER "用户名"@"IP地址" IDENTIFIE ...

  5. (大数据工程师学习路径)第一步 Linux 基础入门----用户及文件权限管理

    用户及文件权限管理 实验介绍 1.Linux 中创建.删除用户,及用户组等操作. 2.Linux 中的文件权限设置. 一.Linux 用户管理 Linux 是一个可以实现多用户登陆的操作系统,比如“李 ...

  6. Linux用户及文件权限管理

    Linux用户及文件权限管理

  7. 实验楼学习linux第一章第三节用户及文件权限管理

    用户及文件权限管理 常用命令 查看用户 whoami 创建用户 sudo adduser 用户名 切换账户 su 用户名 删除账户 sudo deluser 用户名 --remove-home 查看用 ...

  8. WordPress用户角色及其权限管理编辑插件:User Role Editor汉化版

    如果Wordpress默认的用户角色及权限不能满足您的需求,又觉得修改代码编辑用户权限太麻烦.那不妨试试User Role Editor,Wordpress用户角色及其权限管理编辑插件. User R ...

  9. solaris用户与文件权限管理

    此文章已于 20:45:28 2015/3/22 重新发布到 zhuxuekui3 solaris用户与文件权限管理1 类别    「网站分类」Oracle 一.用户与用户组管理 三种用户:超级用户. ...

随机推荐

  1. css媒体查询aspect-ratio宽高比在less中的使用

    css媒体查询有一个 宽高比很方便,aspect-ratio ,可以直接使用宽/高 来进行页面适配   使用样例如下: // 宽高比在((320/50)+(728/90))/2 两个尺寸中间值以内 适 ...

  2. mySql创建带解释的表及给表和字段加注释的实现代码

    1.创建带解释的表 CREATE TABLE test_table( t_id INT(11) PRIMARY KEY AUTO_INCREMENT COMMENT '设置主键自增', t_name ...

  3. [PHP] 新版本PHP7.4与新版本MySQL8认证问题

    mysql8的默认密码加密方式是caching_sha2_password,PHP7.4连接mysql的加密方式也为caching_sha2_password,这个地方要注意. 当为了兼容旧版的客户端 ...

  4. aspx使用KindEditor副文本框插件出现检测到有潜在危险

    web配置添加    <httpRuntime requestValidationMode="2.0" /> aspx页面添加   ValidateRequest=&q ...

  5. metasploit篇

    第一部分:基本使用 1.在kali中metasploit默认使用postgresql作为它的数据库: /etc/init.d/postgresql start 开机自启:update-rc.d pos ...

  6. CodeForces - 1260C(贪心+思维)

    题意 https://vjudge.net/problem/CodeForces-1260C 有一串砖,凡是r的倍数而不是b的倍数必须涂红,凡是b的倍数而不是r的倍数必须涂蓝,是公倍数则选一个涂.把涂 ...

  7. 工具资源系列之给 windows 装个 vmware 虚拟机

    如果长时间处于同一种环境,慢慢得我们会觉得有些无聊,所以适当地出去走走看看外面的世界能带给我们不一样的体验. 所以,何不出去走走,看看另一个世界? 然而,平时需要工作很难抽身无所顾忌地潇洒走开,这是不 ...

  8. aliyun-OSS断点续传

    阿里云OSS断点续传(Java版本) 在工作中发现开发的某项功能在用户网络环境差的时候部分图片无法显示,通过Review代码之后发现原来是图片上传到了国外的亚马逊服务器上,经过讨论决定将图片上传到国内 ...

  9. 纯CSS打造BiliBili样式博客主题

    前言 一直以来,我都在思考如何减少不必要的JS代码,仅通过CSS来实现博客园主题美化.CSS有很多魔法代码,例如:before,iconfont,order,等等,利用好这些技巧,也能实现很好美化效果 ...

  10. matplotlib动态绘图

    目录 package Process 解决中文乱码问题 simple_plot() scatter_plot() three_dimension_scatter() Jupyter notebook ...