您现在的位置是:网站首页> 编程资料编程资料
ASP.NET Core3.1 Ocelot认证的实现_实用技巧_
2023-05-24
347人已围观
简介 ASP.NET Core3.1 Ocelot认证的实现_实用技巧_
1.认证
当客户端通过Ocelot访问下游服务的时候,为了保护下游资源服务器会进行认证鉴权,这时候需要在Ocelot添加认证服务。添加认证服务后,随后Ocelot会基于授权密钥授权每个请求可以访问的资源。用户必须像往常一样在其Startup.cs中注册身份验证服务,但是他们为每次注册提供一个方案(身份验证提供者密钥),例如:
public void ConfigureServices(IServiceCollection services) { var authenticationProviderKey = "TestKey"; services.AddAuthentication() .AddJwtBearer(authenticationProviderKey, x => { }); }在此Ocelot认证项目示例中,TestKey是已注册此提供程序的方案,然后将其映射到网关项目Routes路由中:
{ "Routes": [ { "DownstreamPathTemplate": "/api/customers", "DownstreamScheme": "http", "DownstreamHost": "localhost", "DownstreamPort": 9001, "UpstreamPathTemplate": "/customers", "UpstreamHttpMethod": [ "Get" ], "AuthenticationOptions": { "AuthenticationProviderKey": "TestKey", "AllowedScopes": [] } } ] }Ocelot运行时,它将查看Routes.AuthenticationOptions.AuthenticationProviderKey并检查是否存在使用给定密钥注册的身份验证提供程序。如果不存在,则Ocelot将不会启动,如果存在,则Routes将在执行时使用该提供程序。如果对路由进行身份验证,Ocelot将在执行身份验证中间件时调用与之关联的任何方案。如果请求通过身份验证失败,Ocelot将返回http状态代码401。
2.JWT Tokens Bearer认证
Json Web Token (JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519)。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

2.1JWT令牌结构
在紧凑的形式中,JSON Web Tokens由dot(.)分隔的三个部分组成,它们是:Header头、Payload有效载荷、Signature签名。因此,JWT通常如下所示:xxxxx.yyyyy.zzzzz(Header.Payload.Signature)。
2.1.1Header头
标头通常由两部分组成:令牌的类型,即JWT,以及正在使用的签名算法,例如HMAC SHA256或RSA。例如:
{ "alg": "HS256", "typ": "JWT" }然后,这个JSON被编码为Base64Url,形成JWT的第一部分。
2.1.2Payload有效载荷
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT规定了7个官方字段,供选用。
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。例如:
{ "sub": "1234567890", "name": "John Doe", "admin": true }注意,JWT默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。这个JSON对象也要使用Base64URL算法转成字符串。
2.1.3.Signature签名
Signature部分是前两部分的签名,防止数据篡改。首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照下面的公式产生签名:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
签名用于验证消息在此过程中未被更改,并且,在使用私钥签名的令牌的情况下,它还可以验证JWT的发件人是否是它所声称的人。把他们三个全部放在一起,输出是三个由点分隔的Base64-URL字符串,可以在HTML和HTTP环境中轻松传递,而与基于XML的标准(如SAML)相比更加紧凑。下面显示了一个JWT,它具有先前的头和有效负载编码,并使用机密签名:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoid3prNzAzIiwibmJmIjoiMTU5MjE0MzkzNyIsImV4cCI6MTU5MjE0Mzk5OCwiaXNzIjoiYXV0aC5qd3QuY2MiLCJhdWQiOiJkZW5nd3V8MjAyMC82LzE0IDIyOjEyOjE5In0 .4RiwhRy0rQkZjclOFWyTpmW7v0AMaL3aeve1L-eWIz0
其实一般发送用户名和密码获取token那是由Identity4来完成的,包括验证用户,生成JwtToken。但是项目这里是由System.IdentityModel.Tokens类库来生成JwtToken。最后返回jwt令牌token给用户。JwtToken解码可以通过https://jwt.io/中进行查看。
3.项目演示
3.1APIGateway项目
在该项目中启用身份认证来保护下游api服务,使用JwtBearer认证,将默认的身份验证方案设置为TestKey。在appsettings.json文件中配置认证中密钥(Secret)跟受众(Aud)信息:
{ "Audience": { "Secret": "Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA==", "Iss": "http://www.c-sharpcorner.com/members/catcher-wong", "Aud": "Catcher Wong" } }Startup添加身份认证代码如下:
public void ConfigureServices(IServiceCollection services) { //获取appsettings.json文件中配置认证中密钥(Secret)跟受众(Aud)信息 var audienceConfig = Configuration.GetSection("Audience"); //获取安全秘钥 var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(audienceConfig["Secret"])); //token要验证的参数集合 var tokenValidationParameters = new TokenValidationParameters { //必须验证安全秘钥 ValidateIssuerSigningKey = true, //赋值安全秘钥 IssuerSigningKey = signingKey, //必须验证签发人 ValidateIssuer = true, //赋值签发人 ValidIssuer = audienceConfig["Iss"], //必须验证受众 ValidateAudience = true, //赋值受众 ValidAudience = audienceConfig["Aud"], //是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比 ValidateLifetime = true, //允许的服务器时间偏移量 ClockSkew = TimeSpan.Zero, //是否要求Token的Claims中必须包含Expires RequireExpirationTime = true, }; //添加服务验证,方案为TestKey services.AddAuthentication(o => { o.DefaultAuthenticateScheme = "TestKey"; }) .AddJwtBearer("TestKey", x => { x.RequireHttpsMetadata = false; //在JwtBearerOptions配置中,IssuerSigningKey(签名秘钥)、ValidIssuer(Token颁发机构)、ValidAudience(颁发给谁)三个参数是必须的。 x.TokenValidationParameters = tokenValidationParameters; }); //添加Ocelot网关服务时,包括Secret秘钥、Iss签发人、Aud受众 services.AddOcelot(Configuration); } public async void Configure(IApplicationBuilder app, IHostingEnvironment env) { //使用认证服务 app.UseAuthentication(); //使用Ocelot中间件 await app.UseOcelot(); }3.1.1Identity Server承载JWT Token
在第二小节介绍JWT Token认证时候,我们都知道一般发送用户名和密码获取Token那是由Identity4来完成的,包括验证用户,生成JWT Token。也就是说Identity Server承载了JWT Token认证功能。为了使用IdentityServer承载Token,请像往常一样在ConfigureServices中使用方案(密钥)注册IdentityServer服务。如果您不知道如何执行此操作,请查阅IdentityServer文档。
public void ConfigureServices(IServiceCollection services) { var authenticationProviderKey = "TestKey"; Action options = o => { o.Authority = "https://whereyouridentityserverlives.com"; o.ApiName = "api"; o.SupportedTokens = SupportedTokens.Both; o.ApiSecret = "secret"; }; services.AddAuthentication() .AddIdentityServerAuthentication(authenticationProviderKey, options); services.AddOcelot(); } 在Identity4中是由Authority参数指定OIDC服务地址,OIDC可以自动发现Issuer, IssuerSigningKey等配置,而o.Audience与x.TokenValidationParameters = new TokenValidationParameters { ValidAudience = "api" }是等效的。
3.2AuthServer项目
此服务主要用于客户端请求受保护的资源服务器时,认证后产生客户端需要的JWT Token,生成JWT Token关键代码如下:
[Route("api/[controller]")] public class AuthController : Controller { private IOptions _settings; public AuthController(IOptions settings) { this._settings = settings; } /// ///用户使用 用户名密码 来请求服务器 ///服务器进行验证用户的信息 ///服务器通过验证发送给用户一个token ///客户端存储token,并在每次请求时附送上这个token值, headers: {'Authorization': 'Bearer ' + token} ///服务端验证token值,并返回数据 /// /// /// /// [HttpGet] public IActionResult Get(string name, string pwd) { //验证登录用户名和密码 if (name == "catcher" && pwd == "123") { var now = DateTime.UtcNow; //添加用户的信息,转成一组声明,还可以写入更多用户信息声明 var claims = new Claim[] { //声明主题 new Claim(JwtRegisteredClaimNames.Sub, name), //JWT ID 唯一标识符 new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), //发布时间戳 issued timestamp new Claim(JwtRegisteredClaimNames.Iat, now.ToUniversalTime().ToString(), ClaimValueTypes.Integer64) }; //下面使用 Microsoft.IdentityModel.Tokens帮助库下的类来创建JwtToken //安全秘钥 var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_settings.Value.Secret)); //声明jwt验证参数 var tokenValidationParameters = new TokenValidationParameters { //必须验证安全秘钥 ValidateIssuerSigningKey = true, //赋值安全秘钥 IssuerSigningKey = signingKey, //必须验证签发人 ValidateIssuer = true, //赋值签发人 ValidIssuer = _settings.Value.Iss, //必须验证受众 ValidateAudience = true, //赋值受众 ValidAudience = _settings.Value.Aud, //是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比 ValidateLifetime = true, //允许的服务器时间偏移量 ClockSkew = TimeSpan.Zero, //是否要求Token的Claims中必须包含Expires RequireExpirationTime = true, }; var jwt = new JwtSecurityToken( //jwt签发人 issuer: _settings.Value.Iss, //jwt受众 audience: _settings.Value.Aud, //jwt一组声明 claims: claims, notBefore: now, //jwt令牌过期时间 expires: now.Add(TimeSpan.FromMinutes(2)), //签名凭证: 安全密钥、签名算法 signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256) ); //生成jwt令牌(json web token) var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt); var responseJson = new { access_token = encodedJwt, expires_in = (int)TimeSpan.FromMinutes(2).TotalSeconds }; return Json(responseJson); } else { return Json(""); } } } public class Audience { public string Secret { get; set; } public string Iss { get; set; } public string Aud { get; set; } } appsettings.json文件中配置认证中密钥(Secret)跟受众(Aud)信息:
{ "Audience": { "Secret": "Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA==", "Iss": "http://www.c-sharpcorner.com/members/catcher-wong", "Aud": "Catcher Wong" } }3.3CustomerAPIServices项目
该项目跟APIGateway项目是一样的,为了保护下游api服务,使用JwtBearer认证,将默认的身份验证方案设置为TestKey。在appsettings.json文件中配置认证中密钥(Secret)跟受众(Aud)信息:
{ "Audience": { "Secret": "Y2F0Y2hlciUyMHdvbmclMjBsb3ZlJTIwLm5ldA==", "Iss": "http://www.c-sharpcorner.com/members/catcher-wong", "Aud": "Catcher Wong" } }Startup添加身份认证代码如下:
public void ConfigureServices(IServiceCollection services) { //获取appsettings.json文件中配置认证中密钥(Secret)跟受众(Aud)信息 var audienceConfig = Configuration.GetSection("Audience"); //获取安全秘钥 var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(audienceConfig["Secret"])); //token要验证的参数集合 var tokenValidationParameters = new TokenValidationParameters { //必须验证安全秘钥 ValidateIssuerSigningKey = true, //赋值安全秘钥 IssuerSigningKey = signingKey, //必须验证签发
相关内容
- ASP.NET Core3.1 Ocelot路由的实现_实用技巧_
- .NET Core 源码编译的问题解析_实用技巧_
- 如何在ASP.Net Core中使用Serilog_实用技巧_
- 如何使用ASP.NET创建网站并设计web页面_实用技巧_
- ASP.NET Core 5中如何生成PDF文档_实用技巧_
- asp.net开发微信派发现金红包/H5网页抢红包功能(思路详解)_实用技巧_
- ASP.NET Core扩展库之实体映射使用详解_实用技巧_
- 在ASP.Net Web Forms中使用依赖注入的步骤_实用技巧_
- 详解如何在ASP.Net Core中实现健康检查_实用技巧_
- Springboot服务Docker化自动部署的实现方法_实用技巧_
点击排行
本栏推荐
