Ocelot统一权限验证

Ocelot作为网关,可以用来作统一验证,接上一篇博客Ocelot网关,我们继续

前一篇,我们创建了OcelotGateway网关项目,DemoAAPI项目,DemoBAPI项目,为了验证用户并分发Token,现在还需要添加AuthenticationAPI项目,也是asp.net core web api项目,整体思路是,当用户首次请求(Request)时web服务,网关会判断本请求有无Token,并是否正确,如果没有或不正确,就会反回401 Unauthorized;如果请求调用登录,正确输入用户名或密码,AuthenticationAPI会验证并分发Token;当客户端带上Token再次访问web服务时,网关就会放过本请求,当请求到达web服务时,web服务要对本Token进行授权验证,如果有访问请求的地址,会成功返回应答,负责会提示没有权验,所以只要具有正确的Token,应答返回都是200 OK,因为Token正确,只是没有权限访问请求的内容。
下面创建最重要的一个项目Ocelot.JWTAuthorizePolicy,选.NET Standard的类库作为项目模板创建本项目,本项目的作用是为网关项目(OcelotGateway),web服务项目(DemoAAPI和DemoBAPI),和AuthenticationAPI提供注入JWT或自定义策略的API,关于自定义策略,可参考(http://www.cnblogs.com/axzxs2001/p/7530929.html)
本项目中的组成部分:
Permission.cs

namespace Ocelot.JWTAuthorizePolicy

{

/// <summary>

/// 用户或角色或其他凭据实体

/// </summary>

public class Permission

{

/// <summary>

/// 用户或角色或其他凭据名称

/// </summary>

public virtual string Name

{ get; set; }

/// <summary>

/// 请求Url

/// </summary>

public virtual string Url

{ get; set; }

}

}


PermissionRequirement.cs


using Microsoft.AspNetCore.Authorization;

using Microsoft.IdentityModel.Tokens;

using System;

using System.Collections.Generic;


namespace Ocelot.JWTAuthorizePolicy

{

/// <summary>

/// 必要参数类

/// </summary>

public class PermissionRequirement : IAuthorizationRequirement

{

/// <summary>

/// 无权限action

/// </summary>

public string DeniedAction { get; set; }


/// <summary>

/// 认证授权类型

/// </summary>

public string ClaimType { internal get; set; }

/// <summary>

/// 请求路径

/// </summary>

public string LoginPath { get; set; } = "/Api/Login";

/// <summary>

/// 发行人

/// </summary>

public string Issuer { get; set; }

/// <summary>

/// 订阅人

/// </summary>

public string Audience { get; set; }

/// <summary>

/// 过期时间

/// </summary>

public TimeSpan Expiration { get; set; }

/// <summary>

/// 签名验证

/// </summary>

public SigningCredentials SigningCredentials { get; set; }


/// <summary>

/// 构造

/// </summary>

/// <param name="deniedAction">无权限action</param>

/// <param name="userPermissions">用户权限集合</param>


/// <summary>

/// 构造

/// </summary>

/// <param name="deniedAction">拒约请求的url</param> 

/// <param name="claimType">声明类型</param>

/// <param name="issuer">发行人</param>

/// <param name="audience">订阅人</param>

/// <param name="signingCredentials">签名验证实体</param>

public PermissionRequirement(string deniedAction, string claimType, string issuer, string audience, SigningCredentials signingCredentials, TimeSpan expiration)

{

ClaimType = claimType;

DeniedAction = deniedAction; 

Issuer = issuer;

Audience = audience;

Expiration = expiration;

SigningCredentials = signingCredentials;

}

}

}


PermissionHandler.cs

using Microsoft.AspNetCore.Authentication;

using Microsoft.AspNetCore.Authentication.JwtBearer;

using Microsoft.AspNetCore.Authorization;

using Microsoft.Extensions.DependencyInjection;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Security.Claims;

using System.Threading.Tasks;


namespace Ocelot.JWTAuthorizePolicy

{

/// <summary>

/// 权限授权Handler

/// </summary>

public class PermissionHandler : AuthorizationHandler<PermissionRequirement>

{

/// <summary>

/// 验证方案提供对象

/// </summary>

public IAuthenticationSchemeProvider Schemes { get; set; }

/// <summary>

/// 用户权限集合

/// </summary>

List<Permission> _permissions;

/// <summary>

/// 构造

/// </summary>

/// <param name="schemes"></param>

public PermissionHandler(IAuthenticationSchemeProvider schemes, List<Permission> permissions=null)

{

Schemes = schemes;

_permissions = permissions;

}


protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)

{

//从AuthorizationHandlerContext转成HttpContext,以便取出表求信息

var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext;

//请求Url

var questUrl = httpContext.Request.Path.Value.ToLower();

//判断请求是否停止

var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();

foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())

{

var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler;

if (handler != null && await handler.HandleRequestAsync())

{

context.Fail();

return;

}

}

//判断请求是否拥有凭据,即有没有登录

var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();

if (defaultAuthenticate != null)

{

var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);

//result?.Principal不为空即登录成功

if (result?.Principal != null)

{

httpContext.User = result.Principal;

//权限中是否存在请求的url

if (_permissions!=null&&_permissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0)

{

var name = httpContext.User.Claims.SingleOrDefault(s => s.Type == requirement.ClaimType).Value;

//验证权限

if (_permissions.Where(w => w.Name == name && w.Url.ToLower() == questUrl).Count() == 0)

{

//无权限跳转到拒绝页面 

httpContext.Response.Redirect(requirement.DeniedAction);

context.Succeed(requirement);

return;

}

}

//判断过期时间

if (DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration).Value) >= DateTime.Now)

{

context.Succeed(requirement);

}

else

{

context.Fail();

}

return;

}

}

//判断没有登录时,是否访问登录的url,并且是Post请求,并且是form表单提交类型,否则为失败

if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST")

|| !httpContext.Request.HasFormContentType))

{

context.Fail();

return;

}

context.Succeed(requirement);

}

}

}

JwtToken.cs



using System;

using System.IdentityModel.Tokens.Jwt;

using System.Security.Claims;


namespace Ocelot.JWTAuthorizePolicy

{

/// <summary>

/// JWTToken生成类

/// </summary>

public class JwtToken

{

/// <summary>

/// 获取基于JWT的Token

/// </summary>

/// <param name="username"></param>

/// <returns></returns>

public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement)

{

var now = DateTime.UtcNow;

var jwt = new JwtSecurityToken(

issuer: permissionRequirement.Issuer,

audience: permissionRequirement.Audience,

claims: claims,

notBefore: now,

expires: now.Add(permissionRequirement.Expiration),

signingCredentials: permissionRequirement.SigningCredentials

);

var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

var responseJson = new

{

Status = true,

access_token = encodedJwt,

expires_in = permissionRequirement.Expiration.TotalMilliseconds,

token_type = "Bearer"

};

return responseJson;

}

}

}

OcelotJwtBearerExtension.cs,本类型中的方法分别用于网关,web服务,和验证服务,请参看注释


using Microsoft.AspNetCore.Authentication;

using Microsoft.AspNetCore.Authorization;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.IdentityModel.Tokens;

using System;

using System.Collections.Generic;

using System.Security.Claims;

using System.Text;


namespace Ocelot.JWTAuthorizePolicy

{

/// <summary>

/// Ocelot下JwtBearer扩展

/// </summary>

public static class OcelotJwtBearerExtension

{

/// <summary>

/// 注入Ocelot下JwtBearer,在ocelot网关的Startup的ConfigureServices中调用

/// </summary>

/// <param name="services">IServiceCollection</param>

/// <param name="issuer">发行人</param>

/// <param name="audience">订阅人</param>

/// <param name="secret">密钥</param>

/// <param name="defaultScheme">默认架构</param>

/// <param name="isHttps">是否https</param>

/// <returns></returns>

public static AuthenticationBuilder AddOcelotJwtBearer(this IServiceCollection services, string issuer, string audience, string secret, string defaultScheme, bool isHttps = false)

{

var keyByteArray = Encoding.ASCII.GetBytes(secret);

var signingKey = new SymmetricSecurityKey(keyByteArray);

var tokenValidationParameters = new TokenValidationParameters

{

ValidateIssuerSigningKey = true,

IssuerSigningKey = signingKey,

ValidateIssuer = true,

ValidIssuer = issuer,//发行人

ValidateAudience = true,

ValidAudience = audience,//订阅人

ValidateLifetime = true,

ClockSkew = TimeSpan.Zero,

RequireExpirationTime = true,

};

return services.AddAuthentication(options =>

{

options.DefaultScheme = defaultScheme;

})

.AddJwtBearer(defaultScheme, opt =>

{

//不使用https

opt.RequireHttpsMetadata = isHttps;

opt.TokenValidationParameters = tokenValidationParameters;

});

}


/// <summary>

/// 注入Ocelot jwt策略,在业务API应用中的Startup的ConfigureServices调用

/// </summary>

/// <param name="services">IServiceCollection</param>

/// <param name="issuer">发行人</param>

/// <param name="audience">订阅人</param>

/// <param name="secret">密钥</param>

/// <param name="defaultScheme">默认架构</param>

/// <param name="policyName">自定义策略名称</param>

/// <param name="deniedUrl">拒绝路由</param>

/// <param name="isHttps">是否https</param>

/// <returns></returns>

public static AuthenticationBuilder AddOcelotPolicyJwtBearer(this IServiceCollection services, string issuer, string audience, string secret, string defaultScheme, string policyName, string deniedUrl, bool isHttps = false)

{


var keyByteArray = Encoding.ASCII.GetBytes(secret);

var signingKey = new SymmetricSecurityKey(keyByteArray);

var tokenValidationParameters = new TokenValidationParameters

{

ValidateIssuerSigningKey = true,

IssuerSigningKey = signingKey,

ValidateIssuer = true,

ValidIssuer = issuer,//发行人

ValidateAudience = true,

ValidAudience = audience,//订阅人

ValidateLifetime = true,

ClockSkew = TimeSpan.Zero,

RequireExpirationTime = true,


};

var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

//如果第三个参数,是ClaimTypes.Role,上面集合的每个元素的Name为角色名称,如果ClaimTypes.Name,即上面集合的每个元素的Name为用户名

var permissionRequirement = new PermissionRequirement(

deniedUrl,

ClaimTypes.Role,

issuer,

audience,

signingCredentials,

expiration: TimeSpan.FromHours(10)

);

//注入授权Handler

services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

services.AddSingleton(permissionRequirement);

return services.AddAuthorization(options =>

{

options.AddPolicy(policyName,

policy => policy.Requirements.Add(permissionRequirement));


})

.AddAuthentication(options =>

{

options.DefaultScheme = defaultScheme;

})

.AddJwtBearer(defaultScheme, o =>

{

//不使用https

o.RequireHttpsMetadata = isHttps;

o.TokenValidationParameters = tokenValidationParameters;

});

}

/// <summary>

/// 注入Token生成器参数,在token生成项目的Startup的ConfigureServices中使用

/// </summary>

/// <param name="services">IServiceCollection</param>

/// <param name="issuer">发行人</param>

/// <param name="audience">订阅人</param>

/// <param name="secret">密钥</param>

/// <param name="deniedUrl">拒绝路由</param>

/// <returns></returns>

public static IServiceCollection AddJTokenBuild(this IServiceCollection services, string issuer, string audience, string secret, string deniedUrl)

{

var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret)), SecurityAlgorithms.HmacSha256);

//如果第三个参数,是ClaimTypes.Role,上面集合的每个元素的Name为角色名称,如果ClaimTypes.Name,即上面集合的每个元素的Name为用户名

var permissionRequirement = new PermissionRequirement(

deniedUrl,

ClaimTypes.Role,

issuer,

audience,

signingCredentials,

expiration: TimeSpan.FromHours(10)

);

return services.AddSingleton(permissionRequirement);


}


}

}

接下来看AuthenticationAPI项目:

appsettings.json

{

"Logging": {

"IncludeScopes": false,

"Debug": {

"LogLevel": {

"Default": "Information"

}

},

"Console": {

"LogLevel": {

"Default": "Information"

}

}

},

"Audience": {

"Secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",

"Issuer": "gsw",

"Audience": "everone"

}

}

Startup.cs


using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Ocelot.JWTAuthorizePolicy;


namespace AuthenticationAPI

{

public class Startup

{

public Startup(IConfiguration configuration)

{

Configuration = configuration;

}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)

{

var audienceConfig = Configuration.GetSection("Audience");

//注入OcelotJwtBearer

services.AddJTokenBuild(audienceConfig["Issuer"], audienceConfig["Issuer"], audienceConfig["Secret"], "/api/denied");

services.AddMvc();

}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

{

if (env.IsDevelopment())

{

app.UseDeveloperExceptionPage();

}

app.UseMvc();

}

}

}

PermissionController.cs


using System;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Authorization;

using System.Security.Claims;

using Microsoft.AspNetCore.Authentication.JwtBearer;

using Ocelot.JWTAuthorizePolicy;


namespace AuthenticationAPI

public class PermissionController : Controller

{

/// <summary>

/// 自定义策略参数

/// </summary>

PermissionRequirement _requirement;

public PermissionController(PermissionRequirement requirement)

{

_requirement = requirement;

}

[AllowAnonymous]

[HttpPost("/authapi/login")]

public IActionResult Login(string username, string password)

{

var isValidated = (username == "gsw" && password == "111111")|| (username == "ggg" && password == "222222");

var role=username=="gsw"?"admin" :"system";

if (!isValidated)

{

return new JsonResult(new

{

Status = false,

Message = "认证失败"

});

}

else

//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色

var claims = new Claim[] { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, role), new Claim(ClaimTypes.Expiration ,DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())};

//用户标识

var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);

identity.AddClaims(claims);


var token = JwtToken.BuildJwtToken(claims, _requirement);

return new JsonResult(token);

}

}

}

DemoAAPI项目,DemoBAPI项目类似

appsettings.json与网关,AuthenticationAPI相同
Startup.cs

using System.Collections.Generic;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Logging;

using Ocelot.JWTAuthorizePolicy;


namespace DemoAAPI

{

public class Startup

{

public Startup(IConfiguration configuration)

{

Configuration = configuration;

}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)

{

//读取配置文件

var audienceConfig = Configuration.GetSection("Audience");

services.AddOcelotPolicyJwtBearer(audienceConfig["Issuer"], audienceConfig["Issuer"], audienceConfig["Secret"], "GSWBearer", "Permission", "/demoaapi/denied");


//这个集合模拟用户权限表,可从数据库中查询出来

var permission = new List<Permission> {

new Permission { Url="/demoaapi/values", Name="system"},

new Permission { Url="/", Name="system"} 

};

services.AddSingleton(permission);

services.AddMvc();

}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

{

loggerFactory.AddConsole(Configuration.GetSection("Logging"));

if (env.IsDevelopment())

{

app.UseDeveloperExceptionPage();

}

app.UseMvc();

}

}

}

ValuesController.cs


using System.Collections.Generic;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Mvc;


namespace DemoAAPI.Controllers

{

[Authorize("Permission")]

[Route("demoaapi/[controller]")]

public class ValuesController : Controller

[HttpGet]

public IEnumerable<string> Get()

{

return new string[] { "DemoA服务", "请求" };

}

[AllowAnonymous]

[HttpGet("/demoaapi/denied")]

public IActionResult Denied()

{

return new JsonResult(new

{

Status = false,

Message = "demoaapi你无权限访问"

});

}

}

}

OcelotGateway项目

configuration.json,注意每个连接的AuthenticationOptions. AuthenticationProviderKey,要设置成

{

"ReRoutes": [

{

"DownstreamPathTemplate": "/demoaapi/values",

"DownstreamScheme": "http",

"DownstreamPort": 5001,

"DownstreamHost": "localhost",

"UpstreamPathTemplate": "/demoaapi/values",

"UpstreamHttpMethod": [ "Get" ],

"QoSOptions": {

"ExceptionsAllowedBeforeBreaking": 3,

"DurationOfBreak": 10,

"TimeoutValue": 5000

},

"HttpHandlerOptions": {

"AllowAutoRedirect": false,

"UseCookieContainer": false

},

"AuthenticationOptions": {

"AuthenticationProviderKey": "GSWBearer",

"AllowedScopes": []

}

},

{

"DownstreamPathTemplate": "/demoaapi/denied",

"DownstreamScheme": "http",

"DownstreamPort": 5001,

"DownstreamHost": "localhost",

"UpstreamPathTemplate": "/demoaapi/denied",

"UpstreamHttpMethod": [ "Get" ],

"QoSOptions": {

"ExceptionsAllowedBeforeBreaking": 3,

"DurationOfBreak": 10,

"TimeoutValue": 5000

},

"AuthenticationOptions": {

}

},

{

"DownstreamPathTemplate": "/demobapi/values",

"DownstreamScheme": "http",

"DownstreamPort": 5002,

"DownstreamHost": "localhost",

"UpstreamPathTemplate": "/demobapi/values",

"UpstreamHttpMethod": [ "Get" ],

"QoSOptions": {

"ExceptionsAllowedBeforeBreaking": 3,

"DurationOfBreak": 10,

"TimeoutValue": 5000

},

"HttpHandlerOptions": {

"AllowAutoRedirect": false,

"UseCookieContainer": false

},

"AuthenticationOptions": {

"AuthenticationProviderKey": "GSWBearer",

"AllowedScopes": []

}

},

{

"DownstreamPathTemplate": "/demobapi/denied",

"DownstreamScheme": "http",

"DownstreamPort": 5002,

"DownstreamHost": "localhost",

"UpstreamPathTemplate": "/demobapi/denied",

"UpstreamHttpMethod": [ "Get" ],

"QoSOptions": {

"ExceptionsAllowedBeforeBreaking": 3,

"DurationOfBreak": 10,

"TimeoutValue": 5000

},

"AuthenticationOptions": {

}

},

{

"DownstreamPathTemplate": "/authapi/login",

"DownstreamScheme": "http",

"DownstreamPort": 5003,

"DownstreamHost": "localhost",

"UpstreamPathTemplate": "/authapi/login",

"UpstreamHttpMethod": [ "Get", "Post" ],

"QoSOptions": {

"ExceptionsAllowedBeforeBreaking": 3,

"DurationOfBreak": 10,

"TimeoutValue": 5000

},

"AuthenticationOptions": {

}

}

]

}

Startup.cs


using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Ocelot.DependencyInjection;

using Ocelot.Middleware;

using Ocelot.JWTAuthorizePolicy;

namespace OcelotGateway

{

public class Startup

{

public Startup(IConfiguration configuration)

{

Configuration = configuration;

}

public IConfiguration Configuration { get; } 

public void ConfigureServices(IServiceCollection services)

{

var audienceConfig = Configuration.GetSection("Audience");

//注入OcelotJwtBearer

services.AddOcelotJwtBearer(audienceConfig["Issuer"], audienceConfig["Issuer"], audienceConfig["Secret"], "GSWBearer");

//注入配置文件,AddOcelot要求参数是IConfigurationRoot类型,所以要作个转换

services.AddOcelot(Configuration as ConfigurationRoot);

}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

{

app.UseOcelot().Wait();

}

}

}

接下来是测试项目,创建一个控制项目TestClient

Nuget中添加RestSharp包
Program.cs

using RestSharp;

using System;

using System.Diagnostics;


namespace TestClient

{

class Program

{

/// <summary>

/// 访问Url

/// </summary>

static string _url = "http://127.0.0.1:5000";

static void Main(string[] args)

{


Console.Title = "TestClient";

dynamic token = null;

while (true)

{

Console.WriteLine("1、登录【admin】 2、登录【system】 3、登录【错误用户名密码】 4、查询HisUser数据 5、查询LisUser数据 ");

var mark = Console.ReadLine();

var stopwatch = new Stopwatch();

stopwatch.Start();

switch (mark)

{

case "1":

token = AdminLogin();

break;

case "2":

token = SystemLogin();

break;

case "3":

token = NullLogin();

break;

case "4":

DemoAAPI(token);

break;

case "5":

DemoBAPI(token);

break;

}

stopwatch.Stop();

TimeSpan timespan = stopwatch.Elapsed;

Console.WriteLine($"间隔时间:{timespan.TotalSeconds}");

tokenString = "Bearer " + Convert.ToString(token?.access_token);

}

}

static string tokenString = "";

static dynamic NullLogin()

{

var loginClient = new RestClient(_url);

var loginRequest = new RestRequest("/authapi/login", Method.POST);

loginRequest.AddParameter("username", "gswaa");

loginRequest.AddParameter("password", "111111");

//或用用户名密码查询对应角色

loginRequest.AddParameter("role", "system");

IRestResponse loginResponse = loginClient.Execute(loginRequest);

var loginContent = loginResponse.Content;

Console.WriteLine(loginContent);

return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);

}


static dynamic SystemLogin()

{

var loginClient = new RestClient(_url);

var loginRequest = new RestRequest("/authapi/login", Method.POST);

loginRequest.AddParameter("username", "ggg");

loginRequest.AddParameter("password", "222222");

IRestResponse loginResponse = loginClient.Execute(loginRequest);

var loginContent = loginResponse.Content;

Console.WriteLine(loginContent);

return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);

}

static dynamic AdminLogin()

{

var loginClient = new RestClient(_url);

var loginRequest = new RestRequest("/authapi/login", Method.POST);

loginRequest.AddParameter("username", "gsw");

loginRequest.AddParameter("password", "111111");

IRestResponse loginResponse = loginClient.Execute(loginRequest);

var loginContent = loginResponse.Content;

Console.WriteLine(loginContent);

return Newtonsoft.Json.JsonConvert.DeserializeObject(loginContent);

}

static void DemoAAPI(dynamic token)

{

var client = new RestClient(_url);

//这里要在获取的令牌字符串前加Bearer

string tk = "Bearer " + Convert.ToString(token?.access_token);

client.AddDefaultHeader("Authorization", tk);

var request = new RestRequest("/demoaapi/values", Method.GET);

IRestResponse response = client.Execute(request);

var content = response.Content;

Console.WriteLine($"状态码:{(int)response.StatusCode} 状态信息:{response.StatusCode} 返回结果:{content}");

}

static void DemoBAPI(dynamic token)

{

var client = new RestClient(_url);

//这里要在获取的令牌字符串前加Bearer

string tk = "Bearer " + Convert.ToString(token?.access_token);

client.AddDefaultHeader("Authorization", tk);

var request = new RestRequest("/demobapi/values", Method.GET);

IRestResponse response = client.Execute(request);

var content = response.Content; Console.WriteLine($"状态码:{(int)response.StatusCode} 状态信息:{response.StatusCode} 返回结果:{content}");

}

}

}


相关文章:

  • Ocelot——初识基于.Net Core的API网关

  • Ocelot API网关的实现剖析

  • 微服务网关Ocelot

  • API网关Ocelot 使用Polly 处理部分失败问题

  • 谈谈微服务中的 API 网关(API Gateway)

  • Ocelot网关

原文:http://www.cnblogs.com/axzxs2001/p/8005084.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322639.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot之程序性能监控

转载自 Spring Boot之程序性能监控 Spring Boot特别适合团队构建各种可快速迭代的微服务&#xff0c;同时为了减少程序本身监控系统的开发量&#xff0c;Spring Boot提供了actuator模块&#xff0c;可以很方便的对你的Spring Boot程序做监控。 1. actuator接口说明 Spring B…

laravel部署在linux出现404 not found

laravel项目放在本地服务器后&#xff0c;访问是成功的 http://localhost/blogkjh/public/article 但是在linux服务器上访问显示404 not found 但是我在服务器上使用 php artisan serve --host 0.0.0.0 命令 却可以访问 甚至连swagger都可以访问 关于这个我最近就特别疑…

Visual Studio 2017 15.6版本预览,增加新功能

上周Visual Studio 2017 15.5 版本已正式发布&#xff0c;同时发布的还有 Visual Studio for Mac 7.3 。 Visual Studio 2017 15.6 版本预览&#xff0c;这个最新的预览包含新功能&#xff0c;生产力改进和其他增强功能&#xff0c;以解决客户的反馈意见。 本发行版中的更新摘要…

使用 mono 编译 .NET Standard 应用

微软发布 .NET Standard 2.0 已经有一段时间了&#xff0c; 根据 .NET Standard 2.0 支持版本的文档&#xff0c; Mono 5.4 是支持 .NET Standard 2.0 的&#xff0c; 对于 .NET Standard 2.0 应用的开发的介绍&#xff0c; 几乎全部都是在 Windows 系统下使用 Visual Studio 2…

Spring Boot 热部署入门

转载自 Spring Boot 热部署入门 1. 概述 在日常开发中&#xff0c;我们需要经常修改 Java 代码&#xff0c;手动重启项目&#xff0c;查看修改后的效果。如果在项目小时&#xff0c;重启速度比较快&#xff0c;等待的时间是较短的。但是随着项目逐渐变大&#xff0c;重启的速…

微服务架构的理论基础 - 康威定律

摘要&#xff1a; 可能出乎很多人意料之外的一个事实是&#xff0c;微服务很多核心理念其实在半个世纪前的一篇文章中就被阐述过了&#xff0c;而且这篇文章中的很多论点在软件开发飞速发展的这半个世纪中竟然一再被验证&#xff0c;这就是康威定律。前段时间看了Mike Amundsen…

阿里微服务架构下分布式事务Seata

转载自 阿里微服务架构下分布式事务Seata Seata 是什么&#xff1f; Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。在 Seata 开源之前&#xff0c;Seata 对应的内部版本在阿里经济体内部一直扮演着分布式一…

用于.NET Core的ORM

尽管EF Core正努力提供视图和存储过程等基本数据库特性&#xff0c;但是开发人员也在寻求能满足他们数据访问需求的ORM工具。下面列出一些相对广为使用的ORM。 LLBLGen Pro Runtime Framework LLBLGen Pro Runtime Framework是一种“可选”的ORM&#xff0c;它是与LLBLGen实体建…

Spring Boot之基于Dubbo和Seata的分布式事务解决方案

转载自 Spring Boot之基于Dubbo和Seata的分布式事务解决方案 1. 分布式事务初探 一般来说&#xff0c;目前市面上的数据库都支持本地事务&#xff0c;也就是在你的应用程序中&#xff0c;在一个数据库连接下的操作&#xff0c;可以很容易的实现事务的操作。但是目前&#xff…

Ocelot监控

网关的作用之一&#xff0c;就是有统一的数据出入口&#xff0c;基于这个功能&#xff0c;我们可以在网关上配置监控&#xff0c;从而把所有web服务的请求应答基本数据捕获并展显出来。 关于web的监控&#xff0c;一般的做法是采集数据并保存&#xff0c;然后通过图表的方式展示…

Spring Boot之基于Redis实现MyBatis查询缓存解决方案

转载自 Spring Boot之基于Redis实现MyBatis查询缓存解决方案 1. 前言 MyBatis是Java中常用的数据层ORM框架&#xff0c;笔者目前在实际的开发中&#xff0c;也在使用MyBatis。本文主要介绍了MyBatis的缓存策略、以及基于SpringBoot和Redis实现MyBatis的二级缓存的过程。实现本…

数据库架构演变概要

一&#xff0e;背景为了适应业务增长,数据库数据量快速增长&#xff0c;性能日趋下降&#xff0c;稳定性不佳的实际情况&#xff0c;急需架构逐步演变适应未来的业务发展。二&#xff0e;现状【稳定性】数据库为单点&#xff0c;没有高可用和稳定性方案。【数据量大】数据库目前…

面试请不要再问我Spring Cloud底层原理

转载自 面试请不要再问我Spring Cloud底层原理 概述 毫无疑问&#xff0c;Spring Cloud是目前微服务架构领域的翘楚&#xff0c;无数的书籍博客都在讲解这个技术。不过大多数讲解还停留在对Spring Cloud功能使用的层面&#xff0c;其底层的很多原理&#xff0c;很多人可能并…

nginx配置前端反向代理

本地这里有两个端口&#xff1a; 8080&#xff1a;前端页面 80&#xff1a;后端接口 在nginx配置 listen 8888;server_name 127.0.0.1;location / {root html;proxy_pass http://127.0.0.1:8080;# try_files $uri $uri/ /index.php$is_args$args;index index.html…

Visual Studio 2017的第五个更新包扩展了调试工具

Visual Studio 2017近日收到了最新的完整更新包&#xff0c;版本号为15.5。跟随前几次更新的步伐&#xff0c;这次发布提供了一系列几乎会让所有用户从中受益的特性。此次发布的一个重点是IDE的性能&#xff0c;尤其是减少C#/Visual Basic项目的加载时间。在.NET Core项目中进行…

深港澳大湾区第三次.NET技术交流会圆满成功

2017年12月10日&#xff0c;一场以云、devops、微服务、容器是现在这个发展阶段的软件形态&#xff0c; 本次活动我们围绕这些话题介绍.NET生态下的发展本地社区活动&#xff0c;这次活动还得到如鹏网杨中科老师的大力支持开通网上直播&#xff0c;网上有229位参与活动&#xf…

基于消息中间件RabbitMQ实现简单的RPC服务

转载自 基于消息中间件RabbitMQ实现简单的RPC服务 RPC(Remote Procedure Call,远程过程调用)&#xff0c;是一种计算机通信协议。对于两台机器而言&#xff0c;就是A服务器上的应用程序调用B服务器上的函数或者方法&#xff0c;由于不在同一个内存空间或机器上运行&#xff0c…

开源纯C#工控网关+组态软件(七)数据采集与归档

一、 引子在当前自动化、信息化、智能化的时代背景下&#xff0c;数据的作用日渐凸显。而工业发展到如今&#xff0c;科技含量和自动化水平均显著提高&#xff0c;但对数据的采集、利用才开始起步。对工业企业而言&#xff0c;数据采集日益受到重视&#xff0c;主要应用场景包…

实践出真知之Spring Cloud之基于Eureka、Ribbon、Feign的真实案例

转载自 实践出真知之Spring Cloud之基于Eureka、Ribbon、Feign的真实案例 Eureka是Spring Cloud Eureka的简称&#xff0c;是Netflix提供的组件之一。通过Eureka可以提供服务注册、发现、负载均衡、降级、熔断等功能。本篇主要介绍Eureka作为服务注册中心&#xff0c;以及实现…

从零开发一个laravel项目的增删改查、详情

环境要求&#xff1a; wampcomposer 创建laravel项目&#xff1a; composer create-project --prefer-dist laravel/laravel person快速完成person注册登录开发 1、migration php artisan make:migration create_people_table$table->increments(id);$table->string…