asp.net web api 授权功能
1、重写授权方法
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Net.Http.Headers;
- using System.Web;
- using System.Web.Http;
- using System.Web.Http.Controllers;
- using System.Web.Security;
- using WebAPI.Models;
- using WebAPI.Toolkit;
- namespace WebAPI.Filter
- {
- /// <summary>
- /// 授权
- /// </summary>
- public class RequestAuthorizeAttribute:AuthorizeAttribute
- {
- /// <summary>
- /// 重写授权方法,加入自定义的Ticket验证
- /// </summary>
- /// <param name="actionContext"></param>
- public override void OnAuthorization(HttpActionContext actionContext)
- {
- var isActionAnonymous = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>().Any(a => a is AllowAnonymousAttribute);
- var isControllerAnonymous = actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>().Any(a => a is AllowAnonymousAttribute);
- //如果控制器和动作上允许匿名访问
- if (isControllerAnonymous || isActionAnonymous)
- {
- base.OnAuthorization(actionContext);
- }
- else
- {
- //从http请求的头里面获取身份验证信息,验证是否是请求发起方的ticket
- var headers = actionContext.Request.Headers;
- if ((headers.Authorization != null) && (headers.Authorization.Parameter != null))
- {
- //解密用户ticket,并校验用户名密码是否匹配
- if (ValidateTicket(headers))
- {
- base.IsAuthorized(actionContext);
- }
- else
- {
- HandleUnauthorizedRequest(actionContext);
- }
- }
- else
- {
- HandleUnauthorizedRequest(actionContext);
- }
- }
- }
- /// <summary>
- /// 校验用户身份
- /// </summary>
- /// <param name="headers">请求头</param>
- /// <returns></returns>
- private bool ValidateTicket(HttpRequestHeaders headers)
- {
- //解密Ticket
- var strTicket = FormsAuthentication.Decrypt(headers.Authorization.Parameter).UserData;
- //从Ticket里面获取用户名和密码
- var index = strTicket.IndexOf("&");
- string userName = strTicket.Substring(, index);
- //string password = strTicket.Substring(index + 1);
- //获取令牌
- var token = headers.GetValues("AppId").FirstOrDefault();
- //根据令牌和用户名得到键
- string key = string.Format("{0}_{1}", token, userName);
- //根据缓存键拿到用户信息
- var userInfo = CacheHelper.GetCache(key);
- if (userInfo==null)
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 重写授权失败响应
- /// </summary>
- /// <param name="actionContext"></param>
- protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
- {
- base.HandleUnauthorizedRequest(actionContext);
- actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden, new ResultModel { Status = false, Data = null, ErrorMessage = "您没有权限访问资源" });
- }
- }
- }
2、基类控制器添加授权特性
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Web.Http;
- using System.Web.Http.Controllers;
- using WebAPI.Filter;
- using System.IO;
- using WebAPI.Models;
- using System.Text;
- using WebAPI.Toolkit;
- namespace WebAPI.Controllers
- {
- /// <summary>
- /// 接口基类
- /// </summary>
- [Result]
- [RequestAuthorize]
- public class BaseApiController : ApiController
- {
- /// <summary>
- /// 接口令牌
- /// </summary>
- protected string _token;
- /// <summary>
- ///
- /// </summary>
- protected ApiClient _client;
- /// <summary>
- /// 接口配置
- /// </summary>
- public List<ApiModel> Apis
- {
- get
- {
- string path = string.Format("{0}/config.json", AppDomain.CurrentDomain.BaseDirectory);
- string result = "";
- if (File.Exists(path))
- {
- result = File.ReadAllText(path);
- }
- return JsonConvert.DeserializeObject<List<ApiModel>>(result);
- }
- }
- /// <summary>
- /// 重写接口执行方法
- /// </summary>
- /// <param name="controllerContext">控制器上下文</param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext,CancellationToken cancellationToken)
- {
- try
- {
- var header = controllerContext.Request.Headers;
- _token = header.GetValues("AppId").FirstOrDefault();//接口令牌
- string baseAddress = Apis.FirstOrDefault(a => a.Id == _token).Url;
- _client = new ApiClient(baseAddress, _token, header);
- }
- catch
- {
- var response = new HttpResponseMessage(HttpStatusCode.OK);
- response.Content = new StringContent(JsonConvert.SerializeObject(new ResultModel() { ErrorMessage = "未经授权" }), Encoding.UTF8, "application/json");
- var source = new TaskCompletionSource<HttpResponseMessage>();
- source.SetResult(response);
- return source.Task;
- }
- return base.ExecuteAsync(controllerContext, cancellationToken);
- }
- }
- }
3.登录
- using AppViewModel;
- using AppViewModel.System;
- using System;
- using System.Collections.Generic;
- using System.Dynamic;
- using System.Linq;
- using System.Net;
- using System.Net.Http;
- using System.Web;
- using System.Web.Http;
- using System.Web.Security;
- using WebAPI.Models;
- using WebAPI.Toolkit;
- namespace WebAPI.Controllers.System
- {
- /// <summary>
- /// 用户信息
- /// </summary>
- public class UserController : BaseApiController
- {
- #region 登录
- /// <summary>
- /// 登录
- /// </summary>
- /// <param name="viewModel">登录实体</param>
- /// <returns></returns>
- [HttpPost]
- [AllowAnonymous]
- public UserViewModel Login([FromBody]LoginViewModel viewModel)
- {
- var result = _client.Post(viewModel, "api/SysUser/Login");
- string ticket = string.Empty;
- string key = string.Format("{0}_{1}", _token, viewModel.UserName);
- var userTicket = CacheHelper.GetCache(key);
- if (userTicket == null)
- {
- //生成票据,通常是对用户名和密码进行编码,此处通过用户名和用户名编码进行混淆
- var formTicket = new FormsAuthenticationTicket(, viewModel.UserName, DateTime.Now, DateTime.Now.AddHours(), true, string.Format("{0}&{1}", viewModel.UserName, viewModel.UserName), FormsAuthentication.FormsCookiePath);
- //对票据进行加密
- ticket = FormsAuthentication.Encrypt(formTicket);
- CacheHelper.SetCache(key, ticket, DateTime.Now.AddHours());
- }
- else
- {
- ticket = userTicket.ToString();
- }
- var userModel = new UserViewModel
- {
- Id = result.Data.Id,
- OrgId = result.Data.所属机构Id,
- Name = result.Data.真实姓名,
- Account = result.Data.用户名,
- Token = ticket
- };
- //获取App用户主题
- var userTheme = _client.Get(string.Format("api/SysUserClientConfig/GetByUid?Uid={0}", userModel.Id));
- userModel.ThemeName = (userTheme.Data == null) ? "" : userTheme.Data.ThemeName;
- GetUserPosts(userModel);
- GetUserModules(userModel);
- return userModel;
- }
- /// <summary>
- /// 获取用户岗位列表
- /// </summary>
- /// <param name="userModel"></param>
- private void GetUserPosts(UserViewModel userModel)
- {
- var postResult = _client.Get(string.Format("api/SysBasicPost/GetByUid?Uid={0}", userModel.Id));
- if (postResult.Data == null)
- {
- return;
- }
- foreach (var item in postResult.Data)
- {
- userModel.UserPosts.Add(new PostViewModel() { Id = item.Id, Name = item.岗位名称 });
- }
- }
- /// <summary>
- /// 获取用户模块列表
- /// </summary>
- /// <param name="userModel"></param>
- private void GetUserModules(UserViewModel userModel)
- {
- if (userModel.UserPosts.Count < || userModel.UserPosts.Count > )
- {
- return;
- }
- //默认如果当前用户只有一个岗位就加载用户的模块列表
- var result = _client.Get(string.Format("api/SysModule/Get?Gid={0}&Uid={1}&Pid={2}", userModel.OrgId, userModel.Id, userModel.UserPosts.FirstOrDefault().Id));
- if (result.Data == null)
- {
- return;
- }
- var viewModels = new List<ModuleViewModel>();
- foreach (var item in result.Data)
- {
- viewModels.Add(new ModuleViewModel()
- {
- Id = item.Id,
- PId = item.Pid,
- Name = item.别名,
- Url = item.默认入口页面,
- IconUrl = item.图标URL
- });
- }
- userModel.UserModules = viewModels.Where(a => a.PId == null).ToList();
- if (userModel.UserModules == null || userModel.UserModules.Count < )
- {
- return;
- }
- //包装模块列表
- foreach (var item in userModel.UserModules)
- {
- item.Childs = viewModels.Where(a => a.PId == item.Id).ToList();
- }
- }
- #endregion
- /// <summary>
- /// 获取用户列表
- /// </summary>
- /// <param name="queryModel">机构Id、岗位Id</param>
- /// <returns></returns>
- [HttpPost]
- public List<UserViewModel> GetUsers([FromBody]QueryBaseModel queryModel)
- {
- var result = _client.Get(string.Format("api/SysUser/GetByGidAndPid?Gid={0}&Pid={1}", queryModel.OrgId, queryModel.PostId));
- if (result.Data==null)
- {
- return null;
- }
- var viewModels = new List<UserViewModel>();
- foreach (var item in result.Data)
- {
- viewModels.Add(new UserViewModel(){ Id = item.Id, Name = item.真实姓名 });
- }
- return viewModels;
- }
- /// <summary>
- /// 获取用户详情
- /// </summary>
- /// <param name="userId">用户Id</param>
- /// <returns></returns>
- [HttpPost]
- public UserViewModel GetUserInfo([FromBody]int userId)
- {
- var result = _client.Get(string.Format("api/SysUser/GetById?Id={0}", userId));
- if (result.Data == null)
- {
- return null;
- }
- var viewModel = new UserViewModel()
- {
- Id = result.Data.Id,
- Name = result.Data.真实姓名,
- Tel = result.Data.手机,
- Sex = result.Data.性别,
- Email = result.Data.Email
- };
- return viewModel;
- }
- }
- }
登录参考基础认证的方式,但是为了和网上基础认证做区别没有对用户名和密码进行加密,而是针对用户名和用户名进行加密,加密的核心我认为是打破常规为原则。
如果某个接口不需要授权,则控制器或动作上方添加 [AllowAnonymous] 特性。
注意点:如果重写授权方法没有处理好匿名特性的逻辑,会导致不该认证的接口,打上匿名特性也照样走认证流程。
asp.net web api 授权功能的更多相关文章
- 基于JWT(Json Web Token)的ASP.NET Web API授权方式
token应用流程 初次登录:用户初次登录,输入用户名密码 密码验证:服务器从数据库取出用户名和密码进行验证 生成JWT:服务器端验证通过,根据从数据库返回的信息,以及预设规则,生成JWT 返还JWT ...
- OData services入门----使用ASP.NET Web API描述
http://www.cnblogs.com/muyoushui/archive/2013/01/27/2878844.html ODate 是一种应用层协议,设计它的目的在于提供一组通过HTTP的交 ...
- ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道
Web Host 模式下的路由本质上还是通过ASP.NET 路由系统来进行路由的,只是通过继承和组合的方式对ASP.NET路由系统的内部的类进行了一些封装,产生自己专用一套类结构,功能逻辑基本都是一样 ...
- ASP.NET Web API自身对CORS的支持: CORS授权检验的实施
通过<EnableCorsAttribute特性背后的故事>我们知道:由CorsPolicyProvider提供的CorsPolicy表示目标Action采用的资源授权策略,ASP.NET ...
- ASP.NET Web API Model-ParameterBinding
ASP.NET Web API Model-ParameterBinding 前言 通过上个篇幅的学习了解Model绑定的基础知识,然而在ASP.NET Web API中Model绑定功能模块并不是被 ...
- 使用 SoapUI 测试ASP.NET Web API
我们为不同的目的开发了很多web服务,经过授权的用户就可以访问和使用这些web服务.soapUI 是一个强大的测试web服务的工具,他不仅可以测试SOAP服务,他也支持测试RESTful服务.在这里我 ...
- 跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中,我们通过自定义的HttpMessageHandler自行为ASP.NET Web API实现了针对CORS的支持, ...
- 新作《ASP.NET Web API 2框架揭秘》正式出版
我觉得大部分人都是“眼球动物“,他们关注的往往都是目光所及的东西.对于很多软件从业者来说,他们对看得见(具有UI界面)的应用抱有极大的热忱,但是对背后支撑整个应用的服务却显得较为冷漠.如果我们将整个“ ...
- ASP.NET Web API 2框架揭秘
ASP.NET Web API 2框架揭秘(.NET领域再现力作顶级专家精讲微软全新轻量级通信平台) 蒋金楠 著 ISBN 978-7-121-23536-8 2014年7月出版 定价:108.0 ...
随机推荐
- cookie -- 添加删除
前段时间学到了cookie,之前的公司用的jquery插件,现在终于学到了原生的js <!doctype html> <html> <head> <meta ...
- centos6:一个网卡上显示多个ip地址的错误
网卡显示如下: 上面显示em1有两个ip地址,其中36是设置的固定IP,212这个ip不清楚怎么搞出来的,但是通过212地址也能够正常连接主机.重启网卡之后,还是没有变化. 网卡em1配置如下,/e ...
- L1-022 奇偶分家
给定N个正整数,请统计奇数和偶数各有多少个? 输入格式: 输入第一行给出一个正整N(≤1000):第2行给出N个正整数,以空格分隔. 输出格式: 在一行中先后输出奇数的个数.偶数的个数.中间以1个空格 ...
- 在ant中将依赖jar包一并打包的方法
一般jar包里面是不包含jar文件的,如果自己的类有依赖其他jar包,可以通过ant命令将这些jar包解析,然后和自己的class文件打在一起,命令如下: build.xml 1 2 3 4 5 6 ...
- NBUT 1221 Intermediary 2010辽宁省赛
Time limit 1000 ms Memory limit 131072 kB It is widely known that any two strangers can get to know ...
- E - An Awful Problem 求两段时间内满足条件的天数//lxm
In order to encourage Hiqivenfin to study math, his mother gave him a sweet candy when the day of th ...
- MVC 模型 视图, 控制器 写 三级联动
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- css样式 float的理解
float w3cSchool里解释说, 浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止.由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样 ...
- Redis安装和主要功能简介
Redis安装和主要功能简介 Redis(https://redis.io/), 是一个内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 安装Redis 我很少在开发机中直接装各种数 ...
- SharePoint PeopleEditor控件使用
以下用于简要介绍在SharePoint 2016二次开发中如何使用PeopleEditor人员选择器,并采用前端的方式获取和设置值. 一.在使用的.aspx页面进行注册 <%@ Register ...