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 授权功能的更多相关文章

  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. linux processes

    So that Linux can manage the processes in the system, each process is represented by a task_struct   ...

  2. linux page table entry struct

    Page Table Entry The access control information is held in the PTE and is CPU specific; figure bit f ...

  3. mysql主从搭建之诡异事件

    今天在搭建主从后出现了主库system账号丢失INSERT权限的情况,记录如下 主库: system账号权限同root权限,并且mysql库已经删除 从库: mysql库存在,无system账号 主从 ...

  4. jdk1.6中bin目录下的工具及其作用

    jdk的javaw.javac等的介绍java:在msdos终端窗口中执行.class文件,即解释执行.class文件.通常所说的jvm解释权.javaw:在java自己的窗口中执行.class文件而 ...

  5. L1-040 最佳情侣身高差

    专家通过多组情侣研究数据发现,最佳的情侣身高差遵循着一个公式:(女方的身高)×1.09 =(男方的身高).如果符合,你俩的身高差不管是牵手.拥抱.接吻,都是最和谐的差度. 下面就请你写个程序,为任意一 ...

  6. DevExpress XtraScheduler日程管理控件应用实例(2)-- 深入理解数据存储

    DevExpress年终击穿底价,单套授权低至67折!查看详情>>> 在上篇随笔<DevExpress XtraScheduler日程管理控件应用实例(1)-- 基本使用> ...

  7. SharePoint 网站管理-PowerShell

    1. 显示场中所有可用的网站集 Get-SPSite 2. 显示某一Web应用程序下可用的网站集 Get-SPSite –WebApplication "SharePoint – 80&qu ...

  8. php 文件上传处理

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS4AAACvCAIAAADMuaTdAAAcaklEQVR4nO2da3Abx33Az3H6JdNx2i

  9. 【Genymotion】add a new virtual device 失败

    Genymotion 新增虚拟设备(模拟器)时,由于网络原因,总是下载失败,如图: 下载失败提示“Unable to create virtual device: Connection timeout ...

  10. WKWebView中HTML5获取位置失败

    WKWebView中HTML5获取位置失败,在info.plist文件中添加以下代码打开网页时就会询问是否允许获取位置信息了. <key>NSLocationAlwaysUsageDesc ...