1.需透過一個Code,UserID 到SQL 內做條件的篩選 取得該UserID 是否符合Code的權限範圍
2.所以多設置了一個 AppAuthorizeAttribute 功能 程式碼如下
程式碼說明:
簡單說就是透過Controller 戴帽子方式蓋上去
因為繼承了AuthorizeAttribute,我們改寫原本OnAuthorization 的method
判斷如果有AppFunctionId 這個attribute 就走新的驗證,如果沒有就走原本AuthorizeAttribute 的驗證
接下來我們自訂的AuthorizeCore 也只是再進去SQL裡面SELECT 而已了
完整原始碼
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
namespace IPMS.Filter
{
#region Dependency
using Service.Common;
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using static IPMS.EnumSet;
#endregion
/// <summary>
/// 功能權限驗證機制
/// </summary>
public class AppAuthorizeAttribute : AuthorizeAttribute
{
#region Declare
/// <summary>
/// 功能代號
/// </summary>
public string AppFunctionId { get; set; }
/// <summary>
/// service instance
/// </summary>
private readonly AuthorizeService authorizeService;
#endregion
#region Constructor
public AppAuthorizeAttribute()
{
authorizeService = new AuthorizeService();
}
#endregion
#region 授權驗證 - OnAuthorization()
/// <summary>
/// 授權驗證
/// </summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
//對有進網域的電腦而言不太可能發生
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
//檢查是否有輸入AppFunctionId
if (string.IsNullOrEmpty(AppFunctionId))
{
//沒輸入走原本Authorize機制
base.OnAuthorization(filterContext);
}
else
{
if (!AuthorizeCore(filterContext.HttpContext))
{
// 驗證失敗,導至授權失敗頁,but..彈跳視窗無法跳轉!
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Authorize" },
{ "action", "Failed" }
}
);
}
//驗證有過也不留cache
SetCachePolicy(filterContext);
}
}
#endregion
private void SetCachePolicy(AuthorizationContext filterContext)
{
//怕下一秒把這個人被改成Unauth,但因為上一秒他成功進來過,被瀏覽器cache permission,導致雖然已unauth卻還是進的來,所以set 0
var cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null);
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
if (!Enum.IsDefined(typeof(HttpValidationStatus), validationStatus))
{
throw new InvalidEnumArgumentException(nameof(validationStatus), (int) validationStatus,
typeof(HttpValidationStatus));
}
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}
#region 覆寫AuthorizeAttribute類別的AuthorizeCore方法 - AuthorizeCore()
/// <summary>
/// 覆寫AuthorizeAttribute類別的AuthorizeCore方法
/// </summary>
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string userRole = IdentityStore.Read().UseRole;
if (!httpContext.User.Identity.IsAuthenticated)
{
return false;
}
//角色一 Plan相關程式 直接給權限
var rd = httpContext.Request.RequestContext.RouteData;
string currentController = rd.GetRequiredString("controller").ToLower();
if (currentController == "plan" && userRole == nameof(RoleCode.Unit1_Checker_Rol))
{
return true;
}
//判斷此角色是否有功能權限
if (!authorizeService.GetAuthorization(userRole, AppFunctionId, AppFunctionName))
{
LogSet.LogError(
$@"Invoke GetAuthorization() error.
Input: [roleId={userRole}],
[funcId={AppFunctionId}],
[funcName={AppFunctionName}]
Path: [url={((HttpRequestWrapper)((HttpContextWrapper)httpContext).Request).Path}]");
return false;
}
return true;
}
#endregion
}
}