您的位置:首页 > 编程语言 > ASP

Asp.net MVC中的全局权限验证方法及实现

2012-02-22 14:32 666 查看
       开发过MVC的人都知道,MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制Controller)。 MVC模式的目的就是实现Web系统的职能分工。 Model层实现系统中的业务逻辑。 View层用于与用户的交互。 Controller层是Model与View之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。

        我们的权限验证就添加在控制(Controller)层,这是必然的。验证的机制就是,每一次客户端对于Controller里边的Action的请求之前,都会先验证用户的身份,也就是说,用户每一次对于数据的请求,都会验证当前用户是否有使用该数据的权限。

本文所介绍的MVC身份验证大致分为以下四个部分:

AuthenticationAsserts         授权验证的相关断言

AuthorizationFilter               验证过滤器的构造函数

ControllerActionInvoker      自定义ControllerActionInvoker

DefaultControllerFactory     自定义的ControllerFactory,可以通过ControllerFactory向Controller中植入相关的ActionInvoker

下边先从授权验证的相关断言说起,验证断言的作用是:确定用户的请求是否需要验证和确认是否以验证过。它主要包含以下几个方法:精确的权验验证,确定系统是否需要验证,确定用户是否已经通过验证,以及判断用户是否拥有访问该URL的权限。下边看看代码:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Configuration;
using Membership;
using System.Web;
using User.ServiceImp;
using MVCExtension;

namespace Authorization
{
/// <summary>
/// 授权验证的相关断言。
/// </summary>
public class AuthenticationAsserts
{
/// <summary>
/// 确认系统是否需要权限验证(系统在开发期间,为了开发调试方便,可以不需要权限验证,而在开发完成后,套用框架后才要求验证)。
/// </summary>
/// <returns>如果需要验证,则返回True,否则返回False</returns>
public static bool IsRequireAuthenticate()
{
try
{
return  bool.Parse(ConfigConstString.Instance.IsSOAVlidate);
}
catch
{
return false;
}
}

/// <summary>
/// 判断用户是否已经通过登录验证
/// </summary>
/// <param name="controllerContext">Controller的上下文</param>
/// <returns>如果通过验证,返回True,否则返回False</returns>
public static bool IsAuthenticated(ControllerContext controllerContext)
{
return controllerContext.HttpContext.User.Identity.IsAuthenticated;
}

/// <summary>
/// 判断Action是否标示为避免验证?(AvoidAuthenticateAttribute)
/// </summary>
/// <returns>如果该Action标示为避免验证,返回True,否则返回False。</returns>
public static bool IsActionAvoidAuthenticate(ControllerContext   Controller,   IList<IAuthorizationFilter> filters)
{
bool  _ISSecure =false;
foreach (IAuthorizationFilter filer in filters)
{
if (filer is SecureFilterAttribute)
{
SecureFilterAttribute secureFilterAttribute = (SecureFilterAttribute)filer;
_ISSecure = (bool)secureFilterAttribute.ISSecure;
if (_ISSecure) break;
}
else if (filer is ElinkFilterAttribute)
{
string controller = Controller.Controller.ToString();

string id = HttpContext.Current.Request.Params["ElinkID"];
try
{
Guid linkid = id == null ? Guid.NewGuid() : new Guid(id);
_ISSecure =UserGateway.TenantProvider.IsLinkerSecure(controller, linkid,"");

}
catch(Exception e)
{
_ISSecure = false;
}

break;
}
else if(filer is AccurateFilterAttribute)//链接授权
{
Identity bi = (Identity)Controller.HttpContext.User.Identity;
int userid = bi.UserID;
HttpRequest httpRequest = new HttpRequest(string.Empty, Controller.HttpContext.Request.Url.ToString(), Controller.HttpContext.Request.QueryString.ToString());
bool result = UserGateway.TenantSecurityProvider.IsSignatureUrlsecure(httpRequest,userid);
_ISSecure = result;

}

}
return _ISSecure;
}
/// <summary>
/// 精确授权验证
/// </summary>
/// <param name="Controller"></param>
/// <param name="filters"></param>
/// <returns></returns>
public static bool IsAccurateAuthenticate(ControllerContext Controller, IList<IAuthorizationFilter> filters)
{
bool _ISSecure = true;
foreach (IAuthorizationFilter filer in filters)
{
if (filer is AccurateFilterAttribute)//链接授权
{

Identity bi = (Identity)Controller.HttpContext.User.Identity;
int userid = bi.UserID;

HttpRequest httpRequest = new HttpRequest(string.Empty, Controller.HttpContext.Request.Url.ToString(), Controller.HttpContext.Request.QueryString.ToString());
bool result = UserGateway.TenantSecurityProvider.IsSignatureUrlsecure(httpRequest,
userid);
_ISSecure = result;

}
}
return _ISSecure;
}

/// <summary>
/// 判断用户是否拥有访问该URL的权限。
/// 用户是否授权访问该URL包括两个部分:
///1.用户有该URL对应功能的访问角色;
///2.用户所在租户拥有该功能的使用授权。
/// </summary>
/// <param name="url">当前访问的URL</param>
/// <returns>如果用户有权访问该URL,返回true,否则返回False。</returns>
public static bool IsUserHasPermissionAccess(Type controllerType, string actionName)
{
string  url=HttpContextGateWay.Instance.GetHttpContext().Request.Url.AbsolutePath;
bool result = MembershipProviderGateWay.Instance.IsFuntionUsableByUrl(url);//||MembershipProviderGateWay.Instance.IsFuntionUsableByUrl(fullActionUrl)
return result;
}
}
}


然后就该是过滤器部分了:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using BI.Common.Model;
using User.ServiceImp;
using Membership;

namespace Authorization
{
partial class BIAuthorizationFilter : IAuthorizationFilter
{
private Type _controllerType;
private string _actionName;
private readonly ControllerContext _controllerContext;
private readonly IList<IAuthorizationFilter> _filters;
/// <summary>
/// 自定义验证过滤器的构造函数
/// </summary>
/// <param name="controllerType">当前的controllerType</param>
/// <param name="actionName">当前调用的actionName</param>
public BIAuthorizationFilter(IList<IAuthorizationFilter> filters, Type controllerType, string actionName, ControllerContext controllerContext)
{
_controllerType = controllerType;
_actionName = actionName;
_controllerContext = controllerContext;
_filters = filters;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
//权限验证部分代码
}
/// <summary>
/// 得到完整Url
/// </summary>
/// <returns></returns>
public string GetCurrentFullUrl(AuthorizationContext context)
{
return string.Format("{0}://{1}{2}", context.HttpContext.Request.Url.Scheme, context.HttpContext.Request.Url.Host, c            ontext.HttpContext.Request.RawUrl);
}

private void RedirectToLogin(AuthorizationContext context, string url)
{
context.HttpContext.Response.Redirect(String.Format("{0}?ReturnUrl={1}", FormsAuthentication.LoginUrl, HttpUtility.U            rlEncode(url)));
}
}
}

然后就该说说自定义ControllerActionInvoker了。也就是ControllerAction的回调函数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using BI.Authorization;

namespace BI.Authorization
{
/// <summary>
/// 自定义ControllerActionInvoker
/// </summary>
public class BIControllerActionInvoker:ControllerActionInvoker
{
protected override AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor)
{
//在这里插入自定义的验证Filter
if(filters == null)
{
filters = new List<IAuthorizationFilter>();
}
IAuthorizationFilter filter = new BIAuthorizationFilter(filters, actionDescriptor.ControllerDescriptor.ControllerType, actionDescriptor.ActionName, controllerContext);

filters.Insert(0,filter);

return base.InvokeAuthorizationFilters(controllerContext, filters, actionDescriptor);
}

}
}


最后该说说我们的工厂类了:

自定义的ControllerFactory,可以通过ControllerFactory向Controller中植入相关的ActionInvoker

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace BI.Authorization
{
/// <summary>
/// 自定义的ControllerFactory,可以通过ControllerFactory向Controller中植入相关的ActionInvoker
/// </summary>
public class BIDefaultControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
requestContext.HttpContext.Response.BufferOutput = true;
IController instance = base.GetControllerInstance(requestContext, controllerType);
if (instance != null && typeof(Controller).IsAssignableFrom(controllerType))
{
Controller controller = (Controller)instance;
//依赖注入
controller.ActionInvoker = new BIControllerActionInvoker();
//controller.
return controller;
}
else
{
return instance;
}
}
}
}

到这里就把全部的代码写在上边了。

在使用的时候,只需在Global.asax里边的Application_Start()里边写入我们在路由里边对于我们的方法的注册就好了:

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ControllerBuilder.Current.SetControllerFactory(new BIDefaultControllerFactory());
RegisterRoutes(RouteTable.Routes);
}

到这个时候,我们在Controller里边就不需要打标签了,默认的就是所有的Action都会进行我们提前设计好的权限验证了。

public ActionResult Index()
{
ViewData["ReportName"] = "绩效考核进程报表";
ViewData["EncryptionString"] = str;
return View();
}


到这里就结束了,时间关系,没有讲的很细,不明白的就看代码吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息