博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET MVC5+EF6+EasyUI 后台管理系统(66)-MVC WebApi 用户验证 (2)
阅读量:7106 次
发布时间:2019-06-28

本文共 10503 字,大约阅读时间需要 35 分钟。

前言:

回顾,我们利用webapi简单的登录并进行了同域访问与跨域访问来获得Token,您可以跳转到上一节下载代码来一起动手。

继续的文章,我们接下来演示利用拿到的Token来访问接口,管理接口,利用系统权限管理接口,对每个接口进行授权(管理接口为选读部分,因为你需要阅读最开始权限管理部分(18-27节),才能阅读这部分)

开发环境:

VS2015+无数据库(模拟数据)

   访问密码 8ca3

知识点:

  1. WebApi权限验证
  2. 应用到实际中来
  3. 调试

开始:

1.过滤器验证

  我们之前也是通过过滤器来验证对于Action的操作权限,接口也不例外,在Action切入,在每次访问的时候都附带Token信息,也许你可以通过下列在Http请求头中来附加Token

添加过滤类:SupportFilter并继承AuthorizeAttribute权限筛选器OnAuthorization基类方法

using System.Linq;using System.Web;using System.Web.Http;using System.Web.Security;namespace Apps.WebApi.Core{    public class SupportFilter : AuthorizeAttribute    {        //重写基类的验证方式,加入我们自定义的Ticket验证        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)        {            //url获取token            var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase;            var token = content.Request.QueryString["Token"];            if (!string.IsNullOrEmpty(token))            {                //解密用户ticket,并校验用户名密码是否匹配                if (ValidateTicket(token))                {                    base.IsAuthorized(actionContext);                }                else                {                    HandleUnauthorizedRequest(actionContext);                }            }            //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401            else            {                var attributes = actionContext.ActionDescriptor.GetCustomAttributes
().OfType
(); bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); if (isAnonymous) base.OnAuthorization(actionContext); else HandleUnauthorizedRequest(actionContext); } } //校验用户名密码(对Session匹配,或数据库数据匹配) private bool ValidateTicket(string encryptToken) { //解密Ticket var strTicket = FormsAuthentication.Decrypt(encryptToken).UserData; //从Ticket里面获取用户名和密码 var index = strTicket.IndexOf("&"); string userName = strTicket.Substring(0, index); string password = strTicket.Substring(index + 1); //取得session,不通过说明用户退出,或者session已经过期 var token = HttpContext.Current.Session[userName]; if (token == null) { return false; } //对比session中的令牌 if (token.ToString() == encryptToken) { return true; } return false; } }}

HttpActionContext是无法取到URL的参数的,需要转换为HttpContextBase,这个类我都有注释,很容易看懂。

1.从URL取到Token,利用之前加密的方式来揭秘Token并得出Token中的用户名

2.利用用户名获取Session中的Token

3.ValidateTicket验证,判断Session中的Token是否与获取到的相同?

2.应用到实际当中来

最后对每个Action进行注解,好在调用接口的时候优先判断是否有权限访问

3.运行调试

  调试之前,我们需要写点代码来访问

修改Home Index代码

Token:
利用Token后获得的值:

添加一个按钮和DIV好显示结果:

我们获得了正确的数据。如果没有token,我们的结果将会返回一个401

大家可以下载代码把断点设置在

可以调试程序对于Token处理的顺序!

总结:

本节讲解了如何利用Token在来访问需要授权的接口!利用到了MVC的过滤器,在调用Action时候优先进行权限校验,这样就完成了对用户进行接口授权的样例。

以上部分一般都够用了,如果你(ˇˍˇ) 想~更加深入和细微的粒度授权,那么就要对每个接口进行单独授权

如果你有兴趣,那可以继续阅读下面的对API的管理授权

 

--------------------------------------------------------------------------------------------------------丑陋的分割线-----------------------------------------------------------------------------------------

 

下面将演示如何管理接口,这需要你之前有跟读本系列的18-27节权限才能阅读!因为大部门利用了之前的管理界面的功能和代码,是紧密联系的,不过没有关系,就算你没有学习之前的系列文章,也许也能从本节中获得知识!

知识点:

  1.取所有类库中的Api接口

  2.管理接口

  3.对接口进行授权

  4.在过滤器添加权限验证

开始:

回顾一下我们的模块管理:

管理的是每一个控制器中的Action(操作码)

我们的WebApi也是如此,每个控制器的操作码,在WebApi运行时候把数据填充到SysModule表和SysModuleOperation表中中来

1.取得类库中所有Api接口

这个真的好用,取得的接口,你平时可以用于管理或自动测试接口

//把控制器当成URL,把Aciton当成操作码插入到数据表做为权限设置,类似之前的权限系统            //获得API管理器            Collection
apiColl = GlobalConfiguration.Configuration.Services.GetApiExplorer().ApiDescriptions; ILookup
apiGroups = apiColl.ToLookup(api => api.ActionDescriptor.ControllerDescriptor); foreach (var group in apiGroups) { //-----------插入Action foreach (var m in group) { } }

第一个foreach取得控制器,第二个foreach取得控制器下面的Action。大家把这句话添加到Home的Index中来,跟踪一下,分别可以看到Group和m中模型的属性。

现在知道怎么加表了吧!

foreach (var group in apiGroups)            {                string controllerName = group.Key.ControllerName;                //----------插入控制器                rootModel = m_BLL.GetById(controllerName);                if (rootModel == null)                {                    SysModuleModel model = new SysModuleModel()                    {                        Id = controllerName,                        Name = controllerName,                        EnglishName = "",                        ParentId = "ApiInterfaceAuth",                        Url = "api/"+ controllerName,                        Iconic = "fa fa-television",                        Enable = true,                        Remark = "Api接口授权",                        Sort = 1,                        CreatePerson = "Admin",                        CreateTime = DateTime.Now,                        IsLast = true                    };                    m_BLL.Create(ref errors, model);                }                //-----------插入Action                   foreach (var m in group)                {                    string actionName = m.ActionDescriptor.ActionName;                    SysModuleOperateModel model = operateBLL.GetById(m.ActionDescriptor.ActionName);                    if (model == null)                    {                        model = new SysModuleOperateModel();                        model.Id = controllerName + actionName;                        model.Name = m.Documentation == null ? actionName : m.Documentation;                        model.KeyCode = actionName;                        model.ModuleId = controllerName;                        model.IsValid = true;                        model.Sort = 0;                        operateBLL.Create(ref errors, model);                    }                }            }

运行之后数据库将自动添加,几条数据

2.管理接口

表数据跟我们普通的是没有区别的,在界面想办法做个开关做为切换,我这里做了个下拉来切换类型

 切换下拉时候,改变查询条件

菜单类型切换:
$('#swicthType').combobox({            editable: false,            onSelect: function (record) {                if (record.value == "api") {                    $('#List').treegrid({
"url":'@Url.Action("GetList")?id=ApiInterfaceAuth'}); $('#OptList').datagrid('loadData', { total: 0, rows: [] }); } else { $('#List').treegrid({
"url":'@Url.Action("GetList")?id=0'}); $('#OptList').datagrid('loadData', { total: 0, rows: [] }); } } });

3.对接口进行授权

 授权后可以查询到:

 

为了更好的区分,我将只给超级管理员Get接口的权限

4.在过滤器中添加验证

这时候我们需要复制之前系统中过滤器的验证代码过来使用,并稍作修改为下面代码:

public class SupportFilter : AuthorizeAttribute    {        //重写基类的验证方式,加入我们自定义的Ticket验证        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)        {            //url获取token            var content = actionContext.Request.Properties[ConfigPara.MS_HttpContext] as HttpContextBase;            var token = content.Request.QueryString[ConfigPara.Token];            if (!string.IsNullOrEmpty(token))            {                //解密用户ticket,并校验用户名密码是否匹配                //读取请求上下文中的Controller,Action,Id                var routes = new RouteCollection();                RouteConfig.RegisterRoutes(routes);                RouteData routeData = routes.GetRouteData(content);                //取出区域的控制器Action,id                string controller = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;                string action = actionContext.ActionDescriptor.ActionName;                //URL路径                string filePath = HttpContext.Current.Request.FilePath;                if (LoginUserManage.ValidateTicket(token) && ValiddatePermission(token, controller, action, filePath))                {                    //已经登录,有权限,且没有单机登录限制                    base.IsAuthorized(actionContext);                }                else                {                    HandleUnauthorizedRequest(actionContext);                }            }            //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401            else            {                var attributes = actionContext.ActionDescriptor.GetCustomAttributes
().OfType
(); bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); if (isAnonymous) base.OnAuthorization(actionContext); else HandleUnauthorizedRequest(actionContext); } } public bool ValiddatePermission(string token, string controller, string action, string filePath) { bool bResult = false; List
perm = null; perm = (List
)HttpContext.Current.Session[filePath]; if (perm == null) { SysUserBLL userBLL = new SysUserBLL() { m_Rep = new SysUserRepository(new DBContainer()), sysRightRep = new SysRightRepository(new DBContainer()) }; { var userName = LoginUserManage.DecryptToken(token.Trim()); perm = userBLL.GetPermission(userName, controller);//获取当前用户的权限列表 HttpContext.Current.Session[filePath] = perm;//获取的劝降放入会话由Controller调用 } //查询当前Action 是否有操作权限,大于0表示有,否则没有 int count = perm.Where(a => a.KeyCode.ToLower() == action.ToLower()).Count(); if (count > 0) { bResult = true; } else { bResult = false; LoginUserManage.RedirectUrl(); } } return bResult; } }

这样,访问时候将对当前访问的控制器和Action进行权限校验,没有权限同样返回401

接下来写两个方法测试一下,一个访问Values的Get方法,一个访问Values的Post

 

总结:

  其实基于WebApi的权限他们也是如此设计的,您可以集成到你现有的权限系统来

  感谢你抽时间看完本节,所谓 赞 得高尿得远,嘿嘿...

 本文转自ymnets博客园博客,原文链接:http://www.cnblogs.com/ymnets/p/5721137.html,如需转载请自行联系原作者

你可能感兴趣的文章
递归读取文件夹文件
查看>>
Select 1 from table 分析
查看>>
去掉文件夹的SVN属性
查看>>
Action 和 ActionSupport
查看>>
DHCP服务的应用
查看>>
北京实习总结——记住牛人那些话
查看>>
未越狱的IOS设备添加ibooks字典
查看>>
c 语言 整理
查看>>
SSDCRM for Linux版正式发布用户体验版
查看>>
我的友情链接
查看>>
Requests
查看>>
Android开发性能优化大总结
查看>>
Android界面控件(2)—注册点击事件监听器
查看>>
kali linux virtual box
查看>>
CSS 实现的特殊效果资料汇总
查看>>
kill -2 终止程序,但是生成log
查看>>
2014-04-14---Hadoop的基础学习(九)---简单学习Hadoop生态的组件HBase
查看>>
Maven缺少jar的方式
查看>>
sqlyog 快捷键大全
查看>>
javaScript 自定义对象
查看>>