1.引言

通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证。验证方式非常多,本文就重点介绍一种常用的验证方式:基于JWT的token身份认证方案。

2.前期回顾

Web API系列(一):初识API及手动搭建基本框架

Web API系列(二):灵活多样的路由配置

Web API系列(三):添加接口详细说明及测试

3.认识JWT

JWT是 JSON Web Token 的缩写,是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

3.1 JWT工作流程

这里我们通过一张图了解它的工作流程。

从上图中我们可以看出它是基于Token的身份认证,具体流程:客户端携带用户名和密码请求访问 - 服务器校验用户凭据 - 应用提供一个token给客户端 - 客户端存储token,并且在随后的每一次请求中都带着它 -服务器校验token并返回数据。

3.2JWT结构

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:

  • Header:头部,它有token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)两部分组成;
  • Payload:荷载,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明;
  • Signature:签名,目的是用来验证头部和载荷是否被非法篡改。

通过下图,我们可以直观的看到JWT的组成。

它本质上是一个独立的身份验证令牌,可以包含用户标识、用户角色和权限等信息,以及您可以存储任何其他信息(自包含)。任何人都可以轻松读取和解析,并使用密钥来验证真实性。

4.具体实现

上文介绍了JWT的原理,读者简单了解即可,这里我们通过具体代码来实现。

4.1安装JWT包

通过NuGget管理工具安装JWT包,如下图

4.2添加LoginRequest、AuthInfo和HttpResult三个实体类

在MyWebAPI.Entities中添加相应类

LoginRequest实体

  1. public class LoginRequest
  2. {
  3. public string UserId { get; set; }
  4. public string Password { get; set; }
  5. }

AuthInfo实体类

  1. public class AuthInfo
  2. {
  3. public string UserId { get; set; }
  4. public DateTime Expires { get; set; }
  5. }

HttpResul实体类

  1. public class HttpResult
  2. {
  3. public bool Success { get; set; }
  4. public dynamic Data { get; set; }
  5. public string Message { get; set; }
  6. }

4.3添加SystemController,并添加Login登录方法

具体代码如下:

  1. [RoutePrefix("api/System")]
  2. public class SystemController : ApiController
  3. {
  4. [HttpPost, Route("Login")]
  5. public HttpResult Login([FromBody] LoginRequest loginRequest)
  6. {
  7. if (loginRequest == null) return new HttpResult() { Success = false, Message = "登录信息为空!" };
  8. #region 通过数据库判断登录信息是否正确(这里简化判断)
  9. if (loginRequest.UserId != "admin" || loginRequest.Password != "admin")
  10. {
  11. return new HttpResult() { Success = false, Message = "用户名和密码不正确!" };
  12. }
  13. #endregion
  14. AuthInfo authInfo = new AuthInfo()
  15. {
  16. UserId = loginRequest.UserId,
  17. Expires = DateTime.Now.AddDays(1)
  18. };
  19. const string secretKey = "matanzhang";//口令加密秘钥(应该写到配置文件中)
  20. byte[] key = Encoding.UTF8.GetBytes(secretKey);
  21. IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式
  22. IJsonSerializer serializer = new JsonNetSerializer();//序列化Json
  23. IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密
  24. IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码
  25. var token = encoder.Encode(authInfo, key);//生成令牌
  26. return new HttpResult() { Success = true, Data = token,Message = "登录成功!"};
  27. }
  28. }

4.4添加API过滤器ApiAuthorizeAttribute

具体代码如下:

  1. public class ApiAuthorizeAttribute: AuthorizeAttribute
  2. {
  3. protected override bool IsAuthorized(HttpActionContext actionContext)
  4. {
  5. try
  6. {
  7. var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
  8. var enumerable = authHeader as string[] ?? authHeader.ToArray();
  9. string token = enumerable.FirstOrDefault();
  10. if (string.IsNullOrEmpty(enumerable.FirstOrDefault())) return false;
  11. const string secretKey = "matanzhang";//口令加密秘钥(应该写到配置文件中)
  12. byte[] key = Encoding.UTF8.GetBytes(secretKey);
  13. IJsonSerializer serializer = new JsonNetSerializer();
  14. IDateTimeProvider provider = new UtcDateTimeProvider();
  15. IJwtValidator validator = new JwtValidator(serializer, provider);
  16. IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
  17. IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
  18. IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
  19. //解密
  20. var authInfo = decoder.DecodeToObject<AuthInfo>(token, key, verify: true);
  21. if (authInfo != null)
  22. {
  23. //判断口令过期时间
  24. if (authInfo.Expires < DateTime.Now)
  25. {
  26. return false;
  27. }
  28. actionContext.RequestContext.RouteData.Values.Add("auth", authInfo);
  29. return true;
  30. }
  31. }
  32. catch (Exception e)
  33. {
  34. }
  35. return false;
  36. }
  37. /// <summary>
  38. /// 处理授权失败的请求
  39. /// </summary>
  40. /// <param name="actionContext"></param>
  41. protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
  42. {
  43. var erModel = new HttpResult()
  44. {
  45. Success = false,
  46. Message = "身份认证不正确!"
  47. };
  48. actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, erModel, "application/json");
  49. }
  50. }

4.5在StudentController中添加过滤属性ApiAuthorize

具体如下:

  1. [RoutePrefix("api/Student"),ApiAuthorize]
  2. public class StudentController : ApiController
  3. {
  4. private static readonly List<Student> StudentList = new List<Student>()
  5. {
  6. new Student() {Id = "001", Name = "张三", Sex = "男", Age = 19, Dept = "软件学院"},
  7. new Student() {Id = "002", Name = "李丽", Sex = "女", Age = 19, Dept = "资环学院"}
  8. };
  9. [HttpGet]
  10. public IEnumerable<Student> Get()
  11. {
  12. return StudentList;
  13. }
  14. [HttpGet, Route("GetByDept/{dept}")]
  15. public IEnumerable<Student> GetByDept(string dept)
  16. {
  17. List<Student> tempList = StudentList.Where(p => p.Dept == dept).ToList();
  18. return tempList;
  19. }
  20. [HttpGet]
  21. public Student Get(string id)
  22. {
  23. List<Student> tempList = StudentList.Where(p => p.Id == id).ToList();
  24. return tempList.Count == 1 ? tempList.First() : null;
  25. }
  26. [HttpPost]
  27. public bool Post([FromBody] Student student)
  28. {
  29. if (student == null) return false;
  30. if (StudentList.Where(p => p.Id == student.Id).ToList().Count > 0) return false;
  31. StudentList.Add(student);
  32. return true;
  33. }
  34. [HttpPut]
  35. public bool Put(string id, [FromBody] Student student)
  36. {
  37. if (student == null) return false;
  38. List<Student> tempList = StudentList.Where(p => p.Id == id).ToList();
  39. if (tempList.Count == 0) return false;
  40. Student originStudent = tempList[0];
  41. originStudent.Name = student.Name;
  42. originStudent.Sex = student.Sex;
  43. originStudent.Age = student.Age;
  44. originStudent.Dept = student.Dept;
  45. return true;
  46. }
  47. [HttpDelete]
  48. public bool Delete(string id)
  49. {
  50. List<Student> tempList = StudentList.Where(p => p.Id == id).ToList();
  51. if (tempList.Count == 0) return false;
  52. StudentList.Remove(tempList[0]);
  53. return true;
  54. }
  55. }

依照步骤添加相关代码,此时就完成了JWT验证的添加。

5.通过PostMan测试程序

运行VS,查看相关API接口,如下图所示。

登录前,测试Get:http://localhost:44321/api/Student接口,返回结果如下图所示。

登录,测试Post:http://localhost:44321/api/System/Login接口,返回结果如下图所示。

登录后,测试Get:http://localhost:44321/api/Student接口,返回结果如下图所示。

在APIController上添加权限验证后,访问相应接口时,需要在header里面添加auth属性(token),这样就完成了身份认证。

6.总结

本文介绍了JWT的原理,然后通过代码完成了相应实例教程,博文中的源代码可以通过笔者GitHUb获取。博文写作不易希望多多支持,后续会更新更多内容,感兴趣的朋友可以加关注,欢迎留言交流!也可以通过微信公众搜索“码探长”,联系笔者!

扫描添加下方的微信公众号,获取更多福利和干货!也可通公众号(码探长)联系探长,期待与你相遇!!!

ASP.NET Web API 2系列(四):基于JWT的token身份认证方案的更多相关文章

  1. 基于JWT的token身份认证方案

    一.使用JSON Web Token的好处? 1.性能问题. JWT方式将用户状态分散到了客户端中,相比于session,可以明显减轻服务端的内存压力. Session方式存储用户id的最大弊病在于S ...

  2. 基于JWT的token身份认证方案(转)

    https://www.cnblogs.com/xiangkejin/archive/2018/05/08/9011119.html 一.使用JSON Web Token的好处? 1.性能问题. JW ...

  3. ASP.NET Web API实践系列04,通过Route等特性设置路由

    ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...

  4. ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定

    本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据. 在Models文件夹下创 ...

  5. ASP.NET Web API实践系列05,消息处理管道

    ASP.NET Web API的消息处理管道可以理解为请求到达Controller之前.Controller返回响应之后的处理机制.之所以需要了解消息处理管道,是因为我们可以借助它来实现对请求和响应的 ...

  6. ASP.NET Web API 2系列(三):查看WebAPI接口的详细说明及测试接口

    引言 前边两篇博客介绍了Web API的基本框架以及路由配置,这篇博客主要解决在前后端分离项目中,为前端人员提供详细接口说明的问题,主要是通过修改WebApi HelpPage相关代码和添加WebAp ...

  7. ASP.NET WebApi 基于JWT实现Token签名认证

    一.前言 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebServi ...

  8. .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    上接:.NetCore WebApi——Swagger简单配置 任何项目都有权限这一关键部分.比如我们有许多接口.有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问:以保证重要数据不会泄露 ...

  9. 基于JWT的Token身份验证

    ​ 身份验证,是指通过一定的手段,完成对用户身份的确认.为了及时的识别发送请求的用户身份,我们调研了常见的几种认证方式,cookie.session和token. 1.Cookie ​ cookie是 ...

随机推荐

  1. springboot整合websocket后打包报错:javax.websocket.server.ServerContainer not available

    项目整合了websocket以后,打包多次都没有成功,原来是报错了,报错内容如下: Error starting ApplicationContext. To display the conditio ...

  2. 对于CSS里面我之前不太清楚的伪类,我做一些总结

    格式: 标签 + : + 参数 +{ 可填背景颜色,字体颜色,鼠标样式,加粗等 } a:hover{ color:#f40;} :link表示鼠标点击之前的样式 :hover表示鼠标放上去的样式 :a ...

  3. 2020.5.25 第五篇 Scrum冲刺博客

    Team:银河超级无敌舰队 Project:招新通 项目冲刺集合贴:链接 目录 一.每日站立会议 1.1 会议照片 1.2 项目完成情况 二.项目燃尽图 三.签入记录 3.1 代码/文档签入记录 3. ...

  4. python3.6和pip3:Ubuntu下安装升级与踩坑之路

    本文以Ubuntu16.x系统为例,演示如何安装python3.6和相应环境.安装Python3的机器必须要能访问外网才能进行如下操作! 1. 安装方式 在Ubuntu下安装python有两种方式: ...

  5. jmeter参数化之 【CSV Data Set Config/CSV数据配置文件】

    这里以登录功能为例: 1.新建.txt文件,将参数值写入到txt文件中(多个参数值如:用户名,密码 之间以逗号隔开),将文件放置在想要放置的目录下 2.添加csv数据文件设置 右键线程组->添加 ...

  6. [PyTorch 学习笔记] 2.2 图片预处理 transforms 模块机制

    PyTorch 的数据增强 我们在安装PyTorch时,还安装了torchvision,这是一个计算机视觉工具包.有 3 个主要的模块: torchvision.transforms: 里面包括常用的 ...

  7. 网站被K或者降权后应该如何恢复

    http://www.wocaoseo.com/thread-133-1-1.html     网站被K后应该如何恢复,深圳SEO和大家一起研究一下,其实这类的问题大家经常会遇到,而且这类的文章铺天盖 ...

  8. win10下MinGW的安装与配置(详细步骤)

    一.安装mingw软件 1.进入官网 www.mingw.org 2.点击下载downloads 3.点击下载图标 4.点击install z 5.先选择安装的地址,再点击continue 6.等待相 ...

  9. tomcat服务器java.lang.OutOfMemoryError: PermGen space

    一挂就报内存溢出 下面是TOMCAT日志 JAVA程序是没有报错, Nov 24, 2009 4:07:02 PM org.apache.catalina.core.ApplicationDispat ...

  10. Currency Exchange(SPFA判负环)

    Several currency exchange points are working in our city. Let us suppose that each point specializes ...