博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
asp.net web api 授权功能
阅读量:5244 次
发布时间:2019-06-14

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

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{    ///     /// 授权    ///     public class RequestAuthorizeAttribute:AuthorizeAttribute    {        ///         /// 重写授权方法,加入自定义的Ticket验证        ///         ///         public override void OnAuthorization(HttpActionContext actionContext)        {            var isActionAnonymous = actionContext.ActionDescriptor.GetCustomAttributes
().OfType
().Any(a => a is AllowAnonymousAttribute); var isControllerAnonymous = actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes
().OfType
().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); } } } ///
/// 校验用户身份 /// ///
请求头 ///
private bool ValidateTicket(HttpRequestHeaders headers) { //解密Ticket var strTicket = FormsAuthentication.Decrypt(headers.Authorization.Parameter).UserData; //从Ticket里面获取用户名和密码 var index = strTicket.IndexOf("&"); string userName = strTicket.Substring(0, 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; } ///
/// 重写授权失败响应 /// ///
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{    ///     /// 接口基类    ///     [Result]    [RequestAuthorize]    public class BaseApiController : ApiController    {        ///         /// 接口令牌        ///         protected string _token;        ///         ///         ///         protected ApiClient _client;        ///         /// 接口配置        ///         public List
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
>(result); } } ///
/// 重写接口执行方法 /// ///
控制器上下文 ///
///
public override Task
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
(); 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{    ///     /// 用户信息    ///     public class UserController : BaseApiController    {        #region 登录                ///         /// 登录        ///         /// 登录实体        /// 
[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(0, viewModel.UserName, DateTime.Now, DateTime.Now.AddHours(8), true, string.Format("{0}&{1}", viewModel.UserName, viewModel.UserName), FormsAuthentication.FormsCookiePath); //对票据进行加密 ticket = FormsAuthentication.Encrypt(formTicket); CacheHelper.SetCache(key, ticket, DateTime.Now.AddHours(8)); } 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; } /// /// 获取用户岗位列表 /// /// 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.岗位名称 }); } } /// /// 获取用户模块列表 /// /// private void GetUserModules(UserViewModel userModel) { if (userModel.UserPosts.Count < 1 || userModel.UserPosts.Count > 1) { 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
(); 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 < 1) { return; } //包装模块列表 foreach (var item in userModel.UserModules) { item.Childs = viewModels.Where(a => a.PId == item.Id).ToList(); } } #endregion ///
/// 获取用户列表 /// ///
机构Id、岗位Id ///
[HttpPost] public List
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
(); foreach (var item in result.Data) { viewModels.Add(new UserViewModel(){ Id = item.Id, Name = item.真实姓名 }); } return viewModels; } ///
/// 获取用户详情 /// ///
用户Id ///
[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] 特性。

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

 

转载于:https://www.cnblogs.com/wgx0428/p/9935605.html

你可能感兴趣的文章
JS博客
查看>>
Docx转Doc操作(c#)
查看>>
Docker——error pulling image configuration
查看>>
一条简单的 SQL 执行超过 1000ms,纳尼?
查看>>
Python函数(一)之杵臼之交
查看>>
关于将qt作为max插件ui库所遇到的困难
查看>>
如何设置映射网络驱动器的具体步骤和方法
查看>>
ASP.NET WebApi 基于OAuth2.0实现Token签名认证
查看>>
SendMail与Postfix的架构备忘
查看>>
paip.mysql 性能测试 报告 home right
查看>>
Atitit.跨平台预定义函数 魔术方法 魔术函数 钩子函数 api兼容性草案 v2 q216 java c# php js.docx...
查看>>
283. Move Zeroes把零放在最后面
查看>>
我的函数说明风格
查看>>
ssh 简介
查看>>
26.无向网邻接表类
查看>>
Visual Studio Code 打开.py代码报Linter pylint is not installed解决办法
查看>>
洛谷 p1352 没有上司的舞会 题解
查看>>
Python 数据类型
查看>>
Task 与 Activity
查看>>
Google Guava学习笔记——简介
查看>>