目录

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. DDL、DML、TCL

    一.DDL 1.创建表(CREATE) (1)数据库对大小写不敏感,只对字符串大小写敏感. (2)使用create关键字创建表.(-- 表示注释). 格式: CREATE TABLE 表名( 字段名1 ...

  2. arcgis api for javascript 学习(五) 实现地图绘制工具

    1.本文实现的功能为鼠标与地图之间的交互,能够在地图上绘制不同形状的图形 2.代码部分主要讲到的为Graphic函数的相关功能 <!DOCTYPE html> <html> & ...

  3. [日常] Redis中set集合的使用思考

    公司部门同事有个需求,就是需要把当前另一个部门a中存储的数据全部导出来,自己当前业务b的数据全部导出来,两个要取一下差集,把a中存在,b中不存在的记下来,要去调用某接口把对应的文件删除.这个我感觉可以 ...

  4. 关于如何刷新清除某个特定网站的缓存---基于Chrome浏览器

    今天工作时又发现了一个小技巧 1.打开一个网站如:百度 2.打开F12开发者模式 3.右键浏览器的刷新按钮,会出现三个选项:正常重新加载,硬性重新加载,清空缓存并硬性重新加载 正常重新加载 Ctrl+ ...

  5. CodeForces - 573A (简单数论+模拟)

    题意 https://vjudge.net/problem/CodeForces-573A 有n个数ai​ ,你可以把每个数任意次×2 或×3 ,问能否最终使得每个数相等. 思路 x2和x3只能改变数 ...

  6. 封装查找元素以及集成日志输出,Base模块

    关于查找元素封装,Base模块 """ Selenium 封装基类 封装查找元素以及集成日志输出 """ from HTMLReport i ...

  7. c语言程序设计第1章

    开始记录自己学习c语言的过程,选用的教材是浙江大学何钦铭.颜晖编写的<c语言程序设计>(第3版). 一.第一个程序 /*求阶乘问题.输入一个正整数n,输出n!*/ #include< ...

  8. 2、zabbix3.4的安装

    系统版本:centos7 数据库版本:mysql二进制安装5.7 zabbix:阿里云安装3.4 一.Zabbix的安装 Zabbix3.4版本官方安装手册链接:https://www.zabbix. ...

  9. c# 第35节 类的多态

    本节内容: 1:多态前戏 2:解决多态的知识点 3:多态两个实例 1:多态前戏 多态源自生活中的现象: 阿拉甲,阿拉乙,阿拉丙,阿拉丁,是人这个类产生的四个对象: 他们的父亲说:世界上女的都是女老虎, ...

  10. Spring Boot 自定义Filter

    一.Filter功能 它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servle ...