/// <summary> /// When implemented in a derived class, checks authorization for the subject in the specified context to perform the specified action on the specified resource. /// </summary> /// <param name="context">The authorization context that contains the subject, resource, and action for which authorization is to be checked.</param> /// <returns> /// true if the subject is authorized to perform the specified action on the specified resource; otherwise, false. /// </returns> public override bool CheckAccess(AuthorizationContext context) { bool result = false; // 如果沒有Resource和Operation的情況下,表示可以看 if (context.Resource.Count == 0 && context.Action.Count == 0) { return true; } if (context.Principal.Identity.IsAuthenticated) { string resourceStr = context.Resource.First().Value; string operationStr = context.Action.First().Value; ResourceOperationEnum operation = (ResourceOperationEnum) Enum.Parse(typeof(ResourceOperationEnum), operationStr); ResourceOperation resourceOperation = new ResourceOperation() { ResourceName = resourceStr, Operation = operation }; var rolesName = context.Principal.FindAll(x => x.Type == ClaimTypes.Role) .Select(x => x.Value).ToArray(); result = CheckAccess(context, resourceOperation, rolesName); } return result; }
/// <summary> /// 驗證是否有權限使用某個資源 /// </summary> /// <param name="resource">資源</param> /// <param name="roleId">要驗證的群組Id</param> /// <returns>是否有權限</returns> public bool Authorize(ResourceOperation resource, string roleId) { bool authorized = false; authorized = uow.Repository<RolesOperationPermission>().Reads().Where(x => x.RoleId == roleId && x.ResourceName == resource.ResourceName && (x.Operation & resource.Operation) == resource.Operation).Count() > 0; return authorized; }
/// <summary> /// 驗證是否有權限使用某個資源 /// </summary> /// <param name="resource">資源</param> /// <param name="roleNames">要驗證的群組名稱</param> /// <returns>是否有權限</returns> public bool Authorize(ResourceOperation resource, string[] roleNames) { bool authorized = false; var roleIds = GetRoleIdFromRoleNames(roleNames); foreach (var item in roleIds) { authorized = Authorize(resource, item); if (authorized == true) { break; } } return authorized; }
/// <summary> /// 依照內容建立出AuthorizationContext /// </summary> /// <param name="principal">目前的Principal</param> /// <param name="resourceOperation">目前要驗證的ResourceOperation</param> /// <returns>AuthorizationContext</returns> public AuthorizationContext CreateAuthorizationContext(ClaimsPrincipal principal, ResourceOperation resourceOperation) { var actionClaims = new Collection<Claim>(); var resourceClaims = new Collection<Claim>(); if (resourceOperation != null) { actionClaims.Add(new Claim(ActionType, resourceOperation.Operation.ToString())); resourceClaims.Add(new Claim(ResourceType, resourceOperation.ResourceName)); } return new AuthorizationContext( principal, resourceClaims, actionClaims); }
/// <summary> /// 組合出AuthorizationContext交給ClaimsAuthorizationManager去做是否有權限的判斷 /// </summary> /// <param name="principal">目前的Principal</param> /// <param name="resourceOperation">要檢查的ResourceOperation</param> /// <returns>true,表示有權限,要不然就是fals</returns> public bool CheckAccess(ClaimsPrincipal principal, ResourceOperation resourceOperation) { var authorisationContext = CreateAuthorizationContext(principal, resourceOperation); return AuthorizationManager.CheckAccess(authorisationContext); }
/// <summary> /// 新增某一筆的權限到Role Id /// </summary> /// <param name="roleId">要被新增的Role Id</param> /// <param name="resourcOperation">權限內容</param> private void AddPemissionToRole(string roleId, ResourceOperation resourcOperation) { uow.Repository<RolesOperationPermission>().Create(new RolesOperationPermission() { Operation = resourcOperation.Operation, ResourceName = resourcOperation.ResourceName, RoleId = roleId }); }
/// <summary> /// 取得某一筆RoleId的權限 /// </summary> /// <param name="roleId">要搜索的role Id</param> /// <returns>擁有的權限</returns> public List<ResourceOperation> GetResourceOperationForRole(string roleId) { var result = new List<ResourceOperation>(); foreach (var item in GetRolesPermissionForRole(roleId)) { var temp = new ResourceOperation(); temp.Operation = item.Operation; temp.ResourceName = item.ResourceName; result.Add(temp); } return result; }
/// <summary> /// 檢查是否有權限使用某個ResourceOperation /// </summary> /// <param name="context">目前的AuthorizationContext</param> /// <param name="resourceOperation">要驗證的ResourceOperation</param> /// <param name="rolesName">目前使用者的Role</param> /// <returns>true,表示有權限,不然則是false</returns> public abstract bool CheckAccess(AuthorizationContext context, ResourceOperation resourceOperation, string[] rolesName);
/// Duran 當初alan設計的架構是多一層,避免core被綁死,但起專案沒有比較快,需要起專案會有兩個方法: /// 1. 用原架構起,但與資料庫資料庫綁死,那不如寫死在這邊。 /// 2. 不同的資料庫結構,這段一樣要重寫,加入不同資料庫後,在重新匯入改model,步驟繁瑣 /// 目前直接綁資料庫與model,之後起下一個專案方便。 /// TODO: 需要重購:將data access層抽出重寫?會自動產生資料庫架構?(需要在規劃與思考)。 /// <summary> /// 傳入parse出來的ResourceOperation,方便在做處理 /// 應該是用來記錄操作紀錄用的 /// </summary> /// <param name="resourceOpertation">傳入的ResourceOperation</param> /// <param name="httpContext">The HTTP context.</param> protected virtual void ProcessResourceOperation(ResourceOperation resourceOpertation, HttpContextBase httpContext) { var currentIdentity = httpContext.User.Identity as ClaimsIdentity; if (currentIdentity.FindFirst(ClaimTypes.NameIdentifier) != null) { var routeData = httpContext.Request.RequestContext.RouteData; var area = routeData.Values.ContainsKey("area") == true ? routeData.GetRequiredString("area") : string.Empty; var controller = routeData.GetRequiredString("controller"); var action = routeData.GetRequiredString("action"); var operationLog = new UserOperationLog() { Area = area, Action = action, Controller = controller, VisitDateTime = DateTime.Now, RawUrl = httpContext.Request.RawUrl, UserId = currentIdentity.FindFirst(ClaimTypes.NameIdentifier).Value, IP = httpContext.Request.ServerVariables["REMOTE_ADDR"] }; if (resourceOpertation != null) { operationLog.Operation = resourceOpertation.Operation; operationLog.Resource = resourceOpertation.ResourceName; operationLog.ResourceName = resourceOpertation.DisplayNameWithParent; } else { var siteMap = SiteMaps.Current.RootNode.Descendants.Where(x => x.Controller == controller && x.Area == area && x.Action == action).FirstOrDefault(); var resourceName = string.Empty; if (siteMap != null) { resourceName = siteMap.Title; if (siteMap.ParentNode != null) { resourceName = siteMap.ParentNode.Title + "/" + resourceName; } } operationLog.ResourceName = resourceName; } DB.Repository<UserOperationLog>().Create(operationLog); DB.Save(); } }