背景

在微服务架构下,一般都会按不同的业务或功能将整个系统切分成不同的独立子系统,再通过REST API或RPC进行通讯并相互调用,形成各个子系统之间的串联结构。在这里,我们将采用REST API的通讯方式。

比如:

1、有一个“用户中心”独立子系统名为“Lezhima.UserHub”,是一个基于ASP.NET Core mvc 2.0的项目。

2、有一个处理用户订单的独立子系统名为“Lezhima.UserOrder”,是一个基于ASP.NET Core webp api 2.0的项目。

3、同时还有一个处理用户文件上传的独立子系统名为“Lezhima.UserUpload”,是一个基于ASP.NET Core webp api 2.0的项目。

业务关系如下:

用户成功登录后进入“Lezhima.UserHub”,在用户查看订单时通过前端Ajax调用“Lezhima.UserOrder”的web api接口,在用户上传图片是通过前端Ajax调用“Lezhima.UserUpload”的web api接口。

至此,我们了解了上面的业务关系后,心里一定产生出如下两个问题:

1、如何保障“Lezhima.UserOrder”与“Lezhima.UserUpload”两个独立系统内的web api接口安全,因为它们已经被暴露在了前端。

2、如何在“Lezhima.UserHub”站颁发Token。

那么,带着问题我们下面就结合ASP.NET Core 自带的Jwt技术来讨论具体的实现(也许聪明的你有更好的解决方法,请一定告知我,谢谢)。

Jwt 全名为:JSON Web Token,是一个很成熟的技术,园子里也有很多这方面的知识,我这里就不再重述了。

实现原理

“Lezhima.UserHub”站因为已经做了登录验证,我们暂且认为它是可信的,所以在前端Ajax请求“Lezhima.UserOrder”站的web api接口时先到自已后端去生成一个Token,并随之同本次跨站请求一块携带至“Lezhima.UserOrder”站,“Lezhima.UserOrder”站验证请求头中的Token是否合法,如合法则继续路由到具体方法中,否则结束请求。“Lezhima.UserUpload”站原理与“Lezhima.UserOrder”相同。

实现代码

Lezhima.UserHub颁发Token代码:

  1. /// <summary>
  2. /// 颁发一个指定有效期的Token,并将当前登录的用户id传递进来
  3. /// </summary>
  4. /// <param name="currentUserId"></param>
  5. /// <param name="expiresMinutes"></param>
  6. /// <returns></returns>
  7. public static async Task<string> GetAccessToken(string currentUserId,int expiresMinutes=2)
  8. {
  9. return await Task.Run(() =>
  10. {
  11. //约定私钥,下面三个参数可放到配置文件中
  12. var secret = "NGUzNmNlNzQtZThkZC00YjRh";
  13. //发行者
  14. var iss = "Andre";
  15. //接受者
  16. var aud = "Andre";
  17.  
  18. if (string.IsNullOrEmpty(secret) || string.IsNullOrEmpty(iss) || string.IsNullOrEmpty(aud))
  19. return "";
  20.  
  21. if (string.IsNullOrEmpty(currentUserId))
  22. currentUserId = Guid.NewGuid().ToString();
  23.  
  24. var now = DateTime.UtcNow;
  25. var claims = new Claim[]
  26. {
  27. new Claim(JwtRegisteredClaimNames.Sub, currentUserId),
  28. new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(), ClaimValueTypes.Integer64)
  29. };
  30. var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret));
  31. var jwt = new JwtSecurityToken(
  32. issuer: iss,
  33. audience: aud,
  34. claims: claims,
  35. notBefore: now,
  36. expires: now.Add(TimeSpan.FromMinutes(expiresMinutes)),
  37. signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
  38. );
  39. return new JwtSecurityTokenHandler().WriteToken(jwt); //生成一个新的token
  40. });
  41. }

Lezhima.UserHub前端Ajax跨站请求代码:

  1. //封装一个Ajax请求公共方法
  2. function GetWebDataByObject(url, requestMethon, paramter) {
  3. jQuery.support.cors = true;
  4. apiUrl = 'http://127.0.0.1:8012/';
  5. var token = GetToken(); //调用本站内的Token颁发Web api接口
  6. var result = [];
  7. $.ajax({
  8. type: requestMethon,
  9. url: apiUrl + url,
  10. data: paramter,
  11. async: false,
  12. beforeSend: function (xhr) {
  13. //将Token携带到请求头中
  14. xhr.setRequestHeader("Authorization", "Bearer " + token);
  15. },
  16. success: function (data) {
  17. result = data;
  18. },
  19. error: function (XMLHttpRequest, textStatus, errorThrown) {
  20. // 状态码
  21. console.log(XMLHttpRequest.status);
  22. // 状态
  23. console.log(XMLHttpRequest.readyState);
  24. // 错误信息
  25. console.log(textStatus);
  26. }
  27. });
  28. return result;
  29. }

“Lezhima.UserOrder”站开启Jwt的Token验证,在Startup.cs里添加如下代码:

  1. public IServiceProvider ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddCors();
  4.  
  5. //从配置文件中获取私钥、发行者、接受者三个参数
  6. //三个参数的值必需与颁发Token站相同
  7. var audienceConfig = Configuration.GetSection("Audience");
  8.  
  9. var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(audienceConfig["Secret"]));
  10. var tokenValidationParameters = new TokenValidationParameters
  11. {
  12. ValidateIssuerSigningKey = true,
  13. IssuerSigningKey = signingKey,
  14. ValidateIssuer = true,
  15. ValidIssuer = audienceConfig["Iss"],
  16. ValidateAudience = true,
  17. ValidAudience = audienceConfig["Aud"],
  18. ValidateLifetime = true,
  19. ClockSkew = TimeSpan.Zero,
  20. RequireExpirationTime = true,
  21. };
  22. //注入Jwt验证
  23. services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  24. .AddJwtBearer(options => {
  25. options.RequireHttpsMetadata = false;
  26. options.TokenValidationParameters = tokenValidationParameters;
  27. });
  28.  
  29. services.AddMvc();
  30.  
  31. var builder = new ContainerBuilder();
  32. builder.RegisterModule(new Evolution());
  33. builder.Populate(services);
  34. var container = builder.Build();
  35. return container.Resolve<IServiceProvider>();
  36. }
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. }
  7. app.UseCors(builder =>
  8. builder.WithOrigins("*")
  9. .AllowAnyHeader()
  10. .AllowAnyMethod()
  11. .AllowCredentials()
  12. );
  13. //开启验证
  14. app.UseAuthentication();
  15. app.UseMvc();
  16. }

“Lezhima.UserOrder”站内的控制器里添加验证过滤器[Authorize],如下代码:

  1. [Route("api/[Controller]")]
  2. //添加过滤器后,该控制器内所有Action都将进行Token验证
  3. [Authorize]
  4. public class OrderController : Controller
  5. {
  6.  
  7. }

  

至此,基于ASP.NET Core的Jwt跨站验证Token方案就全部完成了,是不是很简单呀^_^  ^_^ !! 

总结

1、Token颁发者与验证者都必需使用相同的私钥,私钥、发行者、接受者等参数可以放在配置文件中动态配置!

2、在项目Startup类中的ConfigureServices方法内添加注册使用Jwt身份验证的功能。

3、在验证者项目的控制器上或方法上加上过滤器 [Authorize]即可开启身份验证。

声明

本文为作者原创,转载请备注出处与保留原文地址,谢谢。如文章能给您带来帮助,请点下推荐或关注,感谢您的支持!

ASP.NET Core2利用Jwt技术在服务端实现对客户端的身份认证的更多相关文章

  1. centos 6.5环境利用iscsi搭建SAN网络存储服务及服务端target和客户端initiator配置详解

    一.简介 iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运行的SCSI指令集,这种指令集合可以实现在IP网络上运行SCSI协议,使其能够 ...

  2. WebService技术,服务端发布到Tomcat(使用Servlet发布),客户端使用axis2实现(二)

    还是在WebService技术,服务端and客户端JDK-wsimport工具(一)的基础上实现.新建一个包:com.aixs2client.目录结构如下: 一.服务端: 1.还是使用com.webs ...

  3. app开发中如何利用sessionId来实现服务端与客户端保持回话

    app开发中如何利用sessionId来实现服务端与客户端保持回话 这个问题太过于常见,也过于简单,以至于大部分开发者根本没有关注过这个问题,我根据和我沟通的开发者中,总结出来常用的方法有以下几种: ...

  4. 利用多线程使socket服务端可以与多个客户端同时通讯

    利用多线程使socket服务端可以与多个客户端同时通讯 server import socket 1. 符合TCP协议的手机 server = socket.socket(socket.AF_INET ...

  5. WebService技术,服务端and客户端JDK-wsimport工具(一)

    使用webservice服务,需要了解几个名词:soap 简单对象协议.http+xml . WSDL 先看下代码结构: 服务端代码与客户端代码分别处于两不同的包中 一.服务端内容 服务端: @Web ...

  6. 在ASP.NET Core中使用Angular2,以及与Angular2的Token base身份认证

    注:下载本文提到的完整代码示例请访问:How to authorization Angular 2 app with asp.net core web api 在ASP.NET Core中使用Angu ...

  7. “快的打车”创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队! - V2EX

    "快的打车"创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队! - ...

  8. java网络编程TCP传输—流操作—服务端反馈与客户端接收

    在读取完流后,服务端会向客户端返回一些数据,告诉客户端,已经写完了. 在这里和”流操作—拿到源后的写入动作“差不多,客户端同样以byte与Buffered两种缓冲读取作为例子,同时,.也是希望大家给补 ...

  9. [发布]SuperIO v2.2.5 集成OPC服务端和OPC客户端

    SuperIO 下载:本站下载 百度网盘 1.修复串口号大于等于10的时候导致IO未知状态. 2.优化RunIODevice(io)函数内部处理流程,二次开发可以重载这个接口. 3.优化IO接收数据, ...

随机推荐

  1. 10_java之继承和抽象类

    01继承的概述 *A:继承的概念 *a:继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系 *b:在Java中,类的继承是指在一个现有类的基础上去构建一个新的类, 构建出来的新 ...

  2. shell基本语法和执行

    执行脚本: 编写一个简单的脚本test.sh: #! /bin/sh cd .. ls Shell脚本中用#表示注释,相当于C语言的//注释.但如果#位于第一行开头,并且是#!(称为Shebang)则 ...

  3. django之管理静态文件

    管理静态文件 项目中的CSS.图片.js都是静态文件 配置静态文件 在settings 文件中定义静态内容 STATIC_URL = '/static/' STATICFILES_DIRS = [ o ...

  4. 深入探究jvm之GC的算法及种类

    一.GC基本概念 GC(Garbage Collection)垃圾收集,1960年最早在List中使用.在Java中GC回收的对象是堆空间和永久区,可以有效避免程序员人为造成内存泄漏问题.将堆空间和永 ...

  5. apktool.bat

    @echo off if "%PATH_BASE%" == "" set PATH_BASE=%PATH% set PATH=%CD%;%PATH_BASE%; ...

  6. 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module

    1 Background ngx_http_stub_status_module 是一个 Nginx 的内置 HTTP 模块,该模块可以提供 Nginx 的状态信息.默认情况下这个模块是不被编译进来的 ...

  7. git回滚到某个commit 上和 返回最新的版本git

    1. 代码回退 首先你要用git log 查看你要回到的那个本版, 然后用 git reset --hard HEAD^ 回退到上个版本 git reset --hard commit_id 退到/进 ...

  8. cocos2dx 屏幕分辨率问题

    做手机上的软件首先要考虑的就是屏幕分辨率怎么解决.coco2dx已经有了很好的解决方法. 用cocos2dx的python脚本创建工程时默认生成一个Helloworld的demo.我们就以这个demo ...

  9. 集合_java集合框架

    转载自http://blog.csdn.net/zsw101259/article/details/7570033 Java集合框架图 简化图: Java平台提供了一个全新的集合框架.“集合框架”主要 ...

  10. Sqlserver2008 FileStream解决图片存储问题

    SQLserver FileStream的出现就是为了解决对大对象的存储中一个矛盾. 对于图片的存储方式 第一种:方式是存储在数据库里面,这种方式一般使用image字段,或者varbinary(max ...