1、重写授权方法

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Http;
  6. using System.Net.Http.Headers;
  7. using System.Web;
  8. using System.Web.Http;
  9. using System.Web.Http.Controllers;
  10. using System.Web.Security;
  11. using WebAPI.Models;
  12. using WebAPI.Toolkit;
  13.  
  14. namespace WebAPI.Filter
  15. {
  16. /// <summary>
  17. /// 授权
  18. /// </summary>
  19. public class RequestAuthorizeAttribute:AuthorizeAttribute
  20. {
  21. /// <summary>
  22. /// 重写授权方法,加入自定义的Ticket验证
  23. /// </summary>
  24. /// <param name="actionContext"></param>
  25. public override void OnAuthorization(HttpActionContext actionContext)
  26. {
  27. var isActionAnonymous = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>().Any(a => a is AllowAnonymousAttribute);
  28. var isControllerAnonymous = actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>().Any(a => a is AllowAnonymousAttribute);
  29.  
  30. //如果控制器和动作上允许匿名访问
  31. if (isControllerAnonymous || isActionAnonymous)
  32. {
  33. base.OnAuthorization(actionContext);
  34. }
  35. else
  36. {
  37. //从http请求的头里面获取身份验证信息,验证是否是请求发起方的ticket
  38. var headers = actionContext.Request.Headers;
  39. if ((headers.Authorization != null) && (headers.Authorization.Parameter != null))
  40. {
  41. //解密用户ticket,并校验用户名密码是否匹配
  42. if (ValidateTicket(headers))
  43. {
  44. base.IsAuthorized(actionContext);
  45. }
  46. else
  47. {
  48. HandleUnauthorizedRequest(actionContext);
  49. }
  50. }
  51. else
  52. {
  53. HandleUnauthorizedRequest(actionContext);
  54. }
  55. }
  56. }
  57.  
  58. /// <summary>
  59. /// 校验用户身份
  60. /// </summary>
  61. /// <param name="headers">请求头</param>
  62. /// <returns></returns>
  63. private bool ValidateTicket(HttpRequestHeaders headers)
  64. {
  65. //解密Ticket
  66. var strTicket = FormsAuthentication.Decrypt(headers.Authorization.Parameter).UserData;
  67.  
  68. //从Ticket里面获取用户名和密码
  69. var index = strTicket.IndexOf("&");
  70. string userName = strTicket.Substring(, index);
  71. //string password = strTicket.Substring(index + 1);
  72.  
  73. //获取令牌
  74. var token = headers.GetValues("AppId").FirstOrDefault();
  75.  
  76. //根据令牌和用户名得到键
  77. string key = string.Format("{0}_{1}", token, userName);
  78.  
  79. //根据缓存键拿到用户信息
  80. var userInfo = CacheHelper.GetCache(key);
  81. if (userInfo==null)
  82. {
  83. return false;
  84. }
  85. return true;
  86. }
  87.  
  88. /// <summary>
  89. /// 重写授权失败响应
  90. /// </summary>
  91. /// <param name="actionContext"></param>
  92. protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
  93. {
  94. base.HandleUnauthorizedRequest(actionContext);
  95.  
  96. actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden, new ResultModel { Status = false, Data = null, ErrorMessage = "您没有权限访问资源" });
  97. }
  98.  
  99. }
  100. }

2、基类控制器添加授权特性

  1. using Newtonsoft.Json;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Web.Http;
  10. using System.Web.Http.Controllers;
  11. using WebAPI.Filter;
  12. using System.IO;
  13. using WebAPI.Models;
  14. using System.Text;
  15. using WebAPI.Toolkit;
  16.  
  17. namespace WebAPI.Controllers
  18. {
  19. /// <summary>
  20. /// 接口基类
  21. /// </summary>
  22. [Result]
  23. [RequestAuthorize]
  24. public class BaseApiController : ApiController
  25. {
  26. /// <summary>
  27. /// 接口令牌
  28. /// </summary>
  29. protected string _token;
  30. /// <summary>
  31. ///
  32. /// </summary>
  33. protected ApiClient _client;
  34. /// <summary>
  35. /// 接口配置
  36. /// </summary>
  37. public List<ApiModel> Apis
  38. {
  39. get
  40. {
  41. string path = string.Format("{0}/config.json", AppDomain.CurrentDomain.BaseDirectory);
  42. string result = "";
  43. if (File.Exists(path))
  44. {
  45. result = File.ReadAllText(path);
  46. }
  47. return JsonConvert.DeserializeObject<List<ApiModel>>(result);
  48. }
  49. }
  50.  
  51. /// <summary>
  52. /// 重写接口执行方法
  53. /// </summary>
  54. /// <param name="controllerContext">控制器上下文</param>
  55. /// <param name="cancellationToken"></param>
  56. /// <returns></returns>
  57. public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext,CancellationToken cancellationToken)
  58. {
  59. try
  60. {
  61. var header = controllerContext.Request.Headers;
  62. _token = header.GetValues("AppId").FirstOrDefault();//接口令牌
  63. string baseAddress = Apis.FirstOrDefault(a => a.Id == _token).Url;
  64.  
  65. _client = new ApiClient(baseAddress, _token, header);
  66. }
  67. catch
  68. {
  69. var response = new HttpResponseMessage(HttpStatusCode.OK);
  70. response.Content = new StringContent(JsonConvert.SerializeObject(new ResultModel() { ErrorMessage = "未经授权" }), Encoding.UTF8, "application/json");
  71.  
  72. var source = new TaskCompletionSource<HttpResponseMessage>();
  73. source.SetResult(response);
  74. return source.Task;
  75. }
  76. return base.ExecuteAsync(controllerContext, cancellationToken);
  77. }
  78.  
  79. }
  80. }

3.登录

  1. using AppViewModel;
  2. using AppViewModel.System;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Dynamic;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Http;
  9. using System.Web;
  10. using System.Web.Http;
  11. using System.Web.Security;
  12. using WebAPI.Models;
  13. using WebAPI.Toolkit;
  14.  
  15. namespace WebAPI.Controllers.System
  16. {
  17. /// <summary>
  18. /// 用户信息
  19. /// </summary>
  20. public class UserController : BaseApiController
  21. {
  22. #region 登录
  23.  
  24. /// <summary>
  25. /// 登录
  26. /// </summary>
  27. /// <param name="viewModel">登录实体</param>
  28. /// <returns></returns>
  29. [HttpPost]
  30. [AllowAnonymous]
  31. public UserViewModel Login([FromBody]LoginViewModel viewModel)
  32. {
  33. var result = _client.Post(viewModel, "api/SysUser/Login");
  34.  
  35. string ticket = string.Empty;
  36. string key = string.Format("{0}_{1}", _token, viewModel.UserName);
  37.  
  38. var userTicket = CacheHelper.GetCache(key);
  39. if (userTicket == null)
  40. {
  41. //生成票据,通常是对用户名和密码进行编码,此处通过用户名和用户名编码进行混淆
  42. var formTicket = new FormsAuthenticationTicket(, viewModel.UserName, DateTime.Now, DateTime.Now.AddHours(), true, string.Format("{0}&{1}", viewModel.UserName, viewModel.UserName), FormsAuthentication.FormsCookiePath);
  43. //对票据进行加密
  44. ticket = FormsAuthentication.Encrypt(formTicket);
  45. CacheHelper.SetCache(key, ticket, DateTime.Now.AddHours());
  46. }
  47. else
  48. {
  49. ticket = userTicket.ToString();
  50. }
  51.  
  52. var userModel = new UserViewModel
  53. {
  54. Id = result.Data.Id,
  55. OrgId = result.Data.所属机构Id,
  56. Name = result.Data.真实姓名,
  57. Account = result.Data.用户名,
  58. Token = ticket
  59. };
  60.  
  61. //获取App用户主题
  62. var userTheme = _client.Get(string.Format("api/SysUserClientConfig/GetByUid?Uid={0}", userModel.Id));
  63. userModel.ThemeName = (userTheme.Data == null) ? "" : userTheme.Data.ThemeName;
  64.  
  65. GetUserPosts(userModel);
  66.  
  67. GetUserModules(userModel);
  68.  
  69. return userModel;
  70. }
  71.  
  72. /// <summary>
  73. /// 获取用户岗位列表
  74. /// </summary>
  75. /// <param name="userModel"></param>
  76. private void GetUserPosts(UserViewModel userModel)
  77. {
  78. var postResult = _client.Get(string.Format("api/SysBasicPost/GetByUid?Uid={0}", userModel.Id));
  79. if (postResult.Data == null)
  80. {
  81. return;
  82. }
  83. foreach (var item in postResult.Data)
  84. {
  85. userModel.UserPosts.Add(new PostViewModel() { Id = item.Id, Name = item.岗位名称 });
  86. }
  87. }
  88.  
  89. /// <summary>
  90. /// 获取用户模块列表
  91. /// </summary>
  92. /// <param name="userModel"></param>
  93. private void GetUserModules(UserViewModel userModel)
  94. {
  95. if (userModel.UserPosts.Count < || userModel.UserPosts.Count > )
  96. {
  97. return;
  98. }
  99.  
  100. //默认如果当前用户只有一个岗位就加载用户的模块列表
  101. var result = _client.Get(string.Format("api/SysModule/Get?Gid={0}&Uid={1}&Pid={2}", userModel.OrgId, userModel.Id, userModel.UserPosts.FirstOrDefault().Id));
  102. if (result.Data == null)
  103. {
  104. return;
  105. }
  106.  
  107. var viewModels = new List<ModuleViewModel>();
  108. foreach (var item in result.Data)
  109. {
  110. viewModels.Add(new ModuleViewModel()
  111. {
  112. Id = item.Id,
  113. PId = item.Pid,
  114. Name = item.别名,
  115. Url = item.默认入口页面,
  116. IconUrl = item.图标URL
  117. });
  118. }
  119.  
  120. userModel.UserModules = viewModels.Where(a => a.PId == null).ToList();
  121. if (userModel.UserModules == null || userModel.UserModules.Count < )
  122. {
  123. return;
  124. }
  125.  
  126. //包装模块列表
  127. foreach (var item in userModel.UserModules)
  128. {
  129. item.Childs = viewModels.Where(a => a.PId == item.Id).ToList();
  130. }
  131. }
  132.  
  133. #endregion
  134.  
  135. /// <summary>
  136. /// 获取用户列表
  137. /// </summary>
  138. /// <param name="queryModel">机构Id、岗位Id</param>
  139. /// <returns></returns>
  140. [HttpPost]
  141. public List<UserViewModel> GetUsers([FromBody]QueryBaseModel queryModel)
  142. {
  143. var result = _client.Get(string.Format("api/SysUser/GetByGidAndPid?Gid={0}&Pid={1}", queryModel.OrgId, queryModel.PostId));
  144. if (result.Data==null)
  145. {
  146. return null;
  147. }
  148.  
  149. var viewModels = new List<UserViewModel>();
  150. foreach (var item in result.Data)
  151. {
  152. viewModels.Add(new UserViewModel(){ Id = item.Id, Name = item.真实姓名 });
  153. }
  154. return viewModels;
  155. }
  156.  
  157. /// <summary>
  158. /// 获取用户详情
  159. /// </summary>
  160. /// <param name="userId">用户Id</param>
  161. /// <returns></returns>
  162. [HttpPost]
  163. public UserViewModel GetUserInfo([FromBody]int userId)
  164. {
  165. var result = _client.Get(string.Format("api/SysUser/GetById?Id={0}", userId));
  166. if (result.Data == null)
  167. {
  168. return null;
  169. }
  170.  
  171. var viewModel = new UserViewModel()
  172. {
  173. Id = result.Data.Id,
  174. Name = result.Data.真实姓名,
  175. Tel = result.Data.手机,
  176. Sex = result.Data.性别,
  177. Email = result.Data.Email
  178. };
  179. return viewModel;
  180. }
  181.  
  182. }
  183. }

登录参考基础认证的方式,但是为了和网上基础认证做区别没有对用户名和密码进行加密,而是针对用户名和用户名进行加密,加密的核心我认为是打破常规为原则。

如果某个接口不需要授权,则控制器或动作上方添加 [AllowAnonymous] 特性。

注意点:如果重写授权方法没有处理好匿名特性的逻辑,会导致不该认证的接口,打上匿名特性也照样走认证流程。

asp.net web api 授权功能的更多相关文章

  1. 基于JWT(Json Web Token)的ASP.NET Web API授权方式

    token应用流程 初次登录:用户初次登录,输入用户名密码 密码验证:服务器从数据库取出用户名和密码进行验证 生成JWT:服务器端验证通过,根据从数据库返回的信息,以及预设规则,生成JWT 返还JWT ...

  2. OData services入门----使用ASP.NET Web API描述

    http://www.cnblogs.com/muyoushui/archive/2013/01/27/2878844.html ODate 是一种应用层协议,设计它的目的在于提供一组通过HTTP的交 ...

  3. ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道

    Web Host 模式下的路由本质上还是通过ASP.NET 路由系统来进行路由的,只是通过继承和组合的方式对ASP.NET路由系统的内部的类进行了一些封装,产生自己专用一套类结构,功能逻辑基本都是一样 ...

  4. ASP.NET Web API自身对CORS的支持: CORS授权检验的实施

    通过<EnableCorsAttribute特性背后的故事>我们知道:由CorsPolicyProvider提供的CorsPolicy表示目标Action采用的资源授权策略,ASP.NET ...

  5. ASP.NET Web API Model-ParameterBinding

    ASP.NET Web API Model-ParameterBinding 前言 通过上个篇幅的学习了解Model绑定的基础知识,然而在ASP.NET Web API中Model绑定功能模块并不是被 ...

  6. 使用 SoapUI 测试ASP.NET Web API

    我们为不同的目的开发了很多web服务,经过授权的用户就可以访问和使用这些web服务.soapUI 是一个强大的测试web服务的工具,他不仅可以测试SOAP服务,他也支持测试RESTful服务.在这里我 ...

  7. 跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?

    在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中,我们通过自定义的HttpMessageHandler自行为ASP.NET Web API实现了针对CORS的支持, ...

  8. 新作《ASP.NET Web API 2框架揭秘》正式出版

    我觉得大部分人都是“眼球动物“,他们关注的往往都是目光所及的东西.对于很多软件从业者来说,他们对看得见(具有UI界面)的应用抱有极大的热忱,但是对背后支撑整个应用的服务却显得较为冷漠.如果我们将整个“ ...

  9. ASP.NET Web API 2框架揭秘

    ASP.NET Web API 2框架揭秘(.NET领域再现力作顶级专家精讲微软全新轻量级通信平台) 蒋金楠 著   ISBN 978-7-121-23536-8 2014年7月出版 定价:108.0 ...

随机推荐

  1. cookie -- 添加删除

    前段时间学到了cookie,之前的公司用的jquery插件,现在终于学到了原生的js <!doctype html> <html> <head> <meta ...

  2. centos6:一个网卡上显示多个ip地址的错误

    网卡显示如下:  上面显示em1有两个ip地址,其中36是设置的固定IP,212这个ip不清楚怎么搞出来的,但是通过212地址也能够正常连接主机.重启网卡之后,还是没有变化. 网卡em1配置如下,/e ...

  3. L1-022 奇偶分家

    给定N个正整数,请统计奇数和偶数各有多少个? 输入格式: 输入第一行给出一个正整N(≤1000):第2行给出N个正整数,以空格分隔. 输出格式: 在一行中先后输出奇数的个数.偶数的个数.中间以1个空格 ...

  4. 在ant中将依赖jar包一并打包的方法

    一般jar包里面是不包含jar文件的,如果自己的类有依赖其他jar包,可以通过ant命令将这些jar包解析,然后和自己的class文件打在一起,命令如下: build.xml 1 2 3 4 5 6 ...

  5. NBUT 1221 Intermediary 2010辽宁省赛

    Time limit 1000 ms Memory limit 131072 kB It is widely known that any two strangers can get to know ...

  6. 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 ...

  7. MVC 模型 视图, 控制器 写 三级联动

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  8. css样式 float的理解

    float w3cSchool里解释说, 浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止.由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样 ...

  9. Redis安装和主要功能简介

    Redis安装和主要功能简介   Redis(https://redis.io/), 是一个内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 安装Redis 我很少在开发机中直接装各种数 ...

  10. SharePoint PeopleEditor控件使用

    以下用于简要介绍在SharePoint 2016二次开发中如何使用PeopleEditor人员选择器,并采用前端的方式获取和设置值. 一.在使用的.aspx页面进行注册 <%@ Register ...