Asp.net MVC权限设计思考 (二)逻辑部分实现


在我的项目中,我还是使用的LINQ TO SQL ,因为我的项目不会涉及太多很太复杂的数据库操作业务。当然如果设计,我相信LINQ TO SQL的自定义扩展也能满足需求。

使用Repository模式是最近MVC很多项目采用的解决方案,能把原来我们杂乱的LINQ TO SQL统一封装起来。让我们的架构更清晰。

现在来看看具体实现。

IRepository接口:

代码
interfaceIRepository<TEntity>whereTEntity:class
{
IQueryable
<TEntity>FindAll(Expression<Func<TEntity,bool>>exp);
TEntityFind(Expression
<Func<TEntity,bool>>exp);
voidAdd(TEntityentity);
voidDelete(TEntityentity);
voidSave();
}

Repository实现:

代码
publicclassRepository<TEntity>:IRepository<TEntity>whereTEntity:class
{
protectedDAL.CourseCenterDatadb;
publicRepository()
{
db
=newDAL.CourseCenterData();
}


///<summary>
///查找所有数据
///</summary>
///<returns></returns>
publicIQueryable<TEntity>FindAll()
{
returndb.GetTable<TEntity>().Where(p=>1==1);
}

///<summary>
///查找所有数据
///</summary>
///<paramname="exp">条件表达式</param>
///<returns></returns>
publicIQueryable<TEntity>FindAll(Expression<Func<TEntity,bool>>exp)
{
returndb.GetTable<TEntity>().Where(exp);
}

///<summary>
///查找一个数据
///</summary>
///<paramname="exp">条件表达式</param>
///<returns></returns>
publicTEntityFind(Expression<Func<TEntity,bool>>exp)
{
returndb.GetTable<TEntity>().FirstOrDefault(exp);
}

///<summary>
///添加数据
///</summary>
///<paramname="entity">实体</param>
publicvoidAdd(TEntityentity)
{
db.GetTable
<TEntity>().InsertOnSubmit(entity);
}

///<summary>
///删除数据
///</summary>
///<paramname="entity">实体</param>
publicvoidDelete(TEntityentity)
{
db.GetTable
<TEntity>().DeleteOnSubmit(entity);
}

///<summary>
///批量添加数据
///</summary>
///<paramname="entity">实体列表</param>
publicvoidAddAll(IEnumerable<TEntity>entity)
{
db.GetTable
<TEntity>().InsertAllOnSubmit(entity);
}

///<summary>
///批量删除数据
///</summary>
///<paramname="entity">实体列表</param>
publicvoidDeleteAll(IEnumerable<TEntity>entity)
{
db.GetTable
<TEntity>().DeleteAllOnSubmit(entity);
}

///<summary>
///对数据做插入,更新,删除操作
///</summary>
publicvoidSave()
{
db.SubmitChanges();
}

网上已经有很多Repository的例子,但是请注意Find中的条件必须是Expression Tree的扩展,否则在数据查询的SQL语句中,你会发现捕获到的将是select一个表之后再来做数据的查询,这在我们海量数据查询时不允许的。

现在我们已经有了自己的Repository,下面来建立一个数据库视图把我们上一讲需要的数据拿出来。

新建视图ViewRoleGroup,选定一下表和字段

我们通过VS2008新建一个LINQ TO SQL类,拖入这个视图。

然后我们需要思考,这个权限分组视图是系统频繁读取的,需要为他创建一个缓存。

新建一个缓存类Caches:

代码
///<summary>
///缓存操作基类
///</summary>
publicclassCaches
{
///<summary>
///建立缓存
///</summary>
publicstaticobjectTryAddCache(stringkey,objectvalue,CacheDependencydependencies,DateTimeabsoluteExpiration,
TimeSpanslidingExpiration,CacheItemPrioritypriority,CacheItemRemovedCallbackonRemovedCallback)
{
if(HttpRuntime.Cache[key]==null&&value!=null)
returnHttpRuntime.Cache.Add(key,value,dependencies,absoluteExpiration,slidingExpiration,priority,onRemovedCallback);
else
returnnull;
}

///<summary>
///移除缓存
///</summary>
publicstaticobjectTryRemoveCache(stringkey)
{
if(HttpRuntime.Cache[key]!=null)
returnHttpRuntime.Cache.Remove(key);
else
returnnull;
}

///<summary>
///移除键中带某关键字的缓存
///</summary>
publicstaticvoidRemoveMultiCache(stringkeyInclude)
{
IDictionaryEnumeratorCacheEnum
=HttpRuntime.Cache.GetEnumerator();
while(CacheEnum.MoveNext())
{
if(CacheEnum.Key.ToString().IndexOf(keyInclude.ToString())>=0)
HttpRuntime.Cache.Remove(CacheEnum.Key.ToString());
}
}

///<summary>
///移除所有缓存
///</summary>
publicstaticvoidRemoveAllCache()
{
IDictionaryEnumeratorCacheEnum
=HttpRuntime.Cache.GetEnumerator();
while(CacheEnum.MoveNext())
{
HttpRuntime.Cache.Remove(CacheEnum.Key.ToString());
}
}
}

来看看我们的ViewRoleGroupRepository怎么写。

新建类:ViewRoleGroupRepository

代码
publicclassViewRoleGroupRepository:Repository<Models.Database.ViewRoleGroup>
{

///<summary>
///获取权限视图缓存列表,Key:ViewGroupList
///</summary>
///<returns></returns>
publicList<Models.Database.ViewRoleGroup>GetCacheAll()
{
List
<Models.Database.ViewRoleGroup>viewRoleGroup;
stringkey="ViewGroupList";

if(HttpRuntime.Cache[key]!=null)
viewRoleGroup
=(List<Models.Database.ViewRoleGroup>)HttpRuntime.Cache[key];
else
{

viewRoleGroup
=FindAll().ToList();
Caches.TryAddCache(key,viewRoleGroup,
null,Cache.NoAbsoluteExpiration,TimeSpan.FromMinutes(20),System.Web.Caching.CacheItemPriority.Normal,null);
}

returnviewRoleGroup;
}
}

接下来我们将自定义自己的AuthorizeAttribute,

新建类CenterAuthorizeAttribute

代码
publicclassCenterAuthorizeAttribute:AuthorizeAttribute
{

publicoverridevoidOnAuthorization(AuthorizationContextfilterContext)
{

stringaction=(string)filterContext.RouteData.Values["Action"];
stringcontroller=(string)filterContext.RouteData.Values["Controller"];
stringfullName=filterContext.HttpContext.User.Identity.Name;

if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
filterContext.HttpContext.Response.Redirect(
string.Format("~/Account/LogOn?returnUrl={0}",filterContext.HttpContext.Request.Url.PathAndQuery));
else
{
if(newLogin().IsLock(fullName))
thrownewException(string.Format("【用户:{0}】对不起,该用户已被锁定。",fullName));

varr
=newBLL.RoleGroupRepository().GetUserRoleGroup(fullName);
varq
=newBLL.ViewRoleGroupRepository().GetCacheAll().FindAll(c=>
c.RoleID
==r.RoleID&&c.SysAppController==controller&&c.SysAppAction==action&&
(c.StartTime.Equals(
"Anytime",StringComparison.CurrentCultureIgnoreCase)?true:(DateTime.Parse(c.StartTime)<=DateTime.Now))&&
(c.EndTime.Equals(
"Anytime",StringComparison.CurrentCultureIgnoreCase)?true:(DateTime.Parse(c.EndTime)>=DateTime.Now)));
if(q.Count==0)
thrownewException(string.Format("【用户:{0}】对不起,您没有访问该页面的权限。",fullName));
}
}
}

请注意varr=newBLL.RoleGroupRepository().GetUserRoleGroup(fullName);这个是我项目中通过用户名获得用户权限分组的实现,大家参考自己项目修改。

大功告成,那怎么用呢,很简单。创建了需要的权限组,例如

超级管理员 然后把对应的Controller和Action权限加入到组后,在需要的Action上进行标注,例如

[CenterAuthorize]
publicActionResultIndex()
{
ViewData[
"Message"]="WelcometoASP.NETMVC!";
returnView();
}

是不是很简单就通过数据库控制到每个需要权限控制的Action咯?当然很多朋友可能还很迷糊,第一次写这类文章。部分代码也没调试。因为从项目剥离出来,所以大家见谅。

UI部分和数据库的操作这里想滤过啦。这些比较简单的东西,大家应该很容易就能实现咯。

优质内容筛选与推荐>>
1、ASP.NET 3.5 新特性开发向导实践(附项目源码下载)- Part 2
2、[Linux环境编程] Linux系统命令“ls -l”的实现
3、cmd 切换盘符
4、laravel如何引用外部文件
5、消息队列的应用场景和常见的消息队列之间的比较


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn