目录

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. Srping MVC ant路径匹配

    背景 最近有一个功能设计path匹配,开发说支持ant匹配,这是我第一次听说这个词,赶紧补一下功课. Ant匹配规则 1.前言 (1)SpringMVC的路径匹配规则是按照Ant来的,实际上不只是Sp ...

  2. CVE-2019-0708-BlueKeep漏洞复现

    环境 攻击机:Kali Linux IP:192.168.0.108 靶机:Windows Sever 7 SP1 旗舰版 IP:192.168.0.109 Exploit: https://gith ...

  3. Spring Cloud Netflix Ribbon详细介绍及自定义规则策略

    之前文章我们介绍了如何配置具有Ribbon轮询机制的负载均衡策略的消费者,这次来具体了解一下Ribbon的一些细节,以及如何自定义负载均衡策略等. 说一下Ribbon实现负载均衡的大致思路.它通过用@ ...

  4. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  5. Python中线程的使用

    并发:多个任务同一时间段进行 并行:多个任务同一时刻进行 线程的实现 线程模块 Python通过两个标准库_thread 和threading,提供对线程的支持 , threading对_thread ...

  6. [视频教程] ubuntu系统下安装最新版的MySQL

    视频地址: https://www.bilibili.com/video/av69256331/ 官网文档https://dev.mysql.com/doc/mysql-apt-repo-quick- ...

  7. [PHP] 深度解析Nginx下的PHP框架路由实现

    所有的框架处理业务请求时,都会处理URL的路径部分,分配到指定的代码中去处理.实现这一功能的关键就是获取$_SERVER全局变量中对于URL部分的数据 当请求的路径为http://test.com/a ...

  8. nginx 配置实例-负载均衡

    1.实现效果 (1)浏览器地址栏输入地址 http://www.123.com/edu/a.html,负载均衡效果,平均 8080 和 8081 端口中 2.准备工作 (1)准备两台 tomcat 服 ...

  9. 使用flask搭建微信公众号:完成token的验证

    上一篇文章讨论了官方给的例子验证token失败的解决方法:微信公众号token验证失败 想了一下,还是决定不适用web.py这个框架.因为搜了一下他的中文文档不多,学起来可能会有点麻烦.而且看着他没有 ...

  10. 毕业设计代做,各种系统微服务项目ssm项目,员工管理系统,微信小程序,购物商城,二手商城系统,销售系统,等等

    毕业设计代做,各种系统,微服务项目,ssm项目 小程序,商城等,期末作业等都可以,价格好说,长期接单, 有项目说明书,软件介绍相关文档,答辩的时候包过,知识点对接好,给你讲解等, 毕业设计代做,各种系 ...