基于角色的权限控制实现

在现代Web应用中,权限控制是一个核心功能,它确保了用户只能访问他们被授权的资源。本文将介绍一种基于角色的权限控制实现方法,该方法使用.NET MVC和JavaScript技术,为服务器端和客户端提供了一种通用的解决方案。

系统概述

本系统是一个Web应用,它能够对用户进行认证和授权。用户登录后,包括分配给他们的功能在内的用户详细信息被存储为会话对象。在请求页面时,服务器端和客户端将根据用户的角色和权限来控制访问。

工作原理

用户登录时,系统会将用户信息和分配给他们的功能存储在会话对象中。当用户请求页面时,服务器端的PermissionFilter会验证请求;如果用户未认证,则会被重定向到登录页面。同时,PermissionFilter还会根据用户角色分配的功能/权限来授权请求;如果用户未授权,则会渲染一个NotAuthorized页面。

在客户端,PermissionChecker脚本会获取用户被授权的功能的elementControlID,并从DOM中移除其余元素。

技术细节

在数据库中,每个功能都有一个唯一的controlID。在客户端,每个功能都被分配了一个唯一的controlID,使用属性data-feature=""。在服务器端,通过与请求中的控制器名称和操作名称关联的功能来检查访问权限。

工具和技术

本系统使用Visual Studio 2012和.NET MVC技术构建。

数据库架构

每个用户都有一个角色,每个角色被分配了一个或多个功能/操作(例如:添加/编辑/删除等)。每个功能/权限都是一个由控制器名称和操作名称识别的操作,具有唯一的controlID(Name),以便在网页上识别。

使用代码

在服务器端,有一个动作过滤器,它根据分配给登录用户角色的功能/权限来授权调用的动作。它还验证认证;访问AfterLogin页面。对于任何未授权的活动,它返回一个NotAuthorizedToUseThisContent页面。

在客户端,一个脚本会在页面加载和任何Ajax请求完成后,从DOM中移除未分配给登录用户角色的功能。

服务器端 - PermissionFilter.cs

PermissionFilter.cs是一个动作过滤器,它在控制器中的每个请求上运行。它使用分配给登录用户角色的功能/权限的动作和控制器名称来认证和授权(loggedin)。

public override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); HttpRequestBase request = filterContext.HttpContext.Request; HttpResponseBase response = filterContext.HttpContext.Response; if ((request.AcceptTypes.Contains("application/json")) == false) { if (request.IsAjaxRequest()) { // Preventing caching of ajax request in IE browser response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1)); response.Cache.SetValidUntilExpires(false); response.Cache.SetCacheability(HttpCacheability.NoCache); response.Cache.SetNoStore(); } string currentActionName = filterContext.ActionDescriptor.ActionName; string currentControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; // get LoggedInUser Permissions PermissionManager userPermissions = PermissionManager.getPermissions(); // All Features are allowed for SuperAdmin - disablePermissioning if (userPermissions != null) { // For logout page filterContext.Controller.ViewBag.LoggedInAdministrator = PermissionManager.GetLoggedInUser(); if (PermissionManager.enablePermissioningSystem == true) { // Not all actions are feature in the application bool isCurrentActionAFeature = Service.isFeaturePresentInList(userPermissions.allFeatures, currentControllerName, currentActionName); if (isCurrentActionAFeature) { bool hasPermission = false; hasPermission = Service.isFeaturePresentInList(userPermissions.accessibleFeatures, currentControllerName, currentActionName); if (!hasPermission) { // return 'not authorized' content filterContext.Result = new ViewResult { ViewName = "~/Views/shared/unauthorizedactivity.cshtml" }; } } } } // Redirect to login Page else { filterContext.Controller.TempData["Message"] = "Please login to continue."; filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary { { "controller", "home" }, { "action", "login" }, { "Area", "" } }); } } }

服务器端的动作被装饰有PermissionFilter属性,用于过滤对该动作的请求。

客户端 - PermissionChecker.js

这个脚本在页面加载和任何Ajax请求时,从DOM中移除未授权的功能元素。

var allowedFeatureList = new Array(); var enablePermission = false; /* Register ajax complete callback to apply 'Userpermissions' on ajax requests */ /* Ajax OnComplete START*/ // For - Authorizing after ajax response $(document).ajaxComplete(function(event, request, settings) { var allDataFeatureElements = $('[data-feature]'); if (enablePermission == true) { $(allDataFeatureElements).each(function() { var currentfid = $(this).data("feature"); // Check If the current data-feature element in Page lies in allowed Features list var result = $.inArray(currentfid, allowedFeatureList); if (result != -1) { } else { // Remove element from DOM if not authorized to access it $(this).addClass("noDisplay"); $(this).remove(); } }); } }); /* Ajax OnComplete END*/ // For - Authorizing after page load $(function() { // To disable caching of ajax requests in IE browsers $.ajaxSetup({ cache: false }); var allDataFeatureElements = $('[data-feature]'); // Get allowed Features List for login user $.getJSON("/home/getAllAccessibleFeatureControlIDJSON", function(data) { enablePermission = data.enablePerm; if (data.enablePerm == true) { for (var i = 0; i < data.controlIDS.length; i++) { allowedFeatureList.push(data.controlIDS[i]); } $(allDataFeatureElements).each(function() { var currentfid = $(this).data("feature"); var result = $.inArray(currentfid, allowedFeatureList); if (result != -1) { } else { $(this).addClass("noDisplay"); $(this).remove(); } }); } }); });

页面加载和ajaxComplete函数用于DOM过滤。功能仅在页面加载时从服务器获取,并在ajaxComplete中使用,因为如果在ajaxComplete中获取,会再次触发它,最终导致无限循环。

功能识别

在用户列表页面中,登录用户仅被分配了EditUser权限,其他功能通过脚本从页面中移除。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485