源码下载地址:下载

项目结构如下图:

在Identity Server授权中,实现IResourceOwnerPasswordValidator接口:

public class IdentityValidator : IResourceOwnerPasswordValidator
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IHttpContextAccessor _httpContextAccessor;
public IdentityValidator(
UserManager<ApplicationUser> userManager,
IHttpContextAccessor httpContextAccessor)
{
_userManager = userManager;
_httpContextAccessor = httpContextAccessor;
} public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
string userName = context.UserName;
string password = context.Password; var user = await _userManager.FindByNameAsync(userName);
if (user == null)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient, "用户不存在!");
return;
} var checkResult = await _userManager.CheckPasswordAsync(user, password);
if (checkResult)
{
context.Result = new GrantValidationResult(
subject: user.Id,
authenticationMethod: "custom",
claims: _httpContextAccessor.HttpContext.User.Claims);
}
else
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "无效的客户身份!");
}
}
}

单页面应用中,使用implicit的授权模式,需添加oidc-client.js,调用API的关键代码:

var config = {
authority: "http://localhost:5000/",
client_id: "JsClient",
redirect_uri: "http://localhost:5500/callback.html",
response_type: "id_token token",
scope:"openid profile UserApi",
post_logout_redirect_uri: "http://localhost:5500/index.html",
};
var mgr = new Oidc.UserManager(config); mgr.getUser().then(function (user) {
if (user) {
log("User logged in", user.profile);
}
else {
log("User not logged in");
}
}); function login() {
mgr.signinRedirect();
} //api调用之前需登录
function api() {
mgr.getUser().then(function (user) {
if (user == null || user == undefined) {
login();
}
var url = "http://localhost:9000/api/Values"; var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
log(xhr.status, JSON.parse(xhr.responseText));
alert(xhr.responseText);
}
xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
xhr.setRequestHeader("sub", user.profile.sub);//这里拿到的是用户ID,传给API端进行角色权限验证
xhr.send();
});
} function logout() {
mgr.signoutRedirect();
}

统一网关通过Ocelot实现,添加Ocelot.json文件,并修改Program.cs文件:

        public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, builder) => {
builder
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("Ocelot.json");
})
.UseUrls("http://+:9000")
.UseStartup<Startup>()
.Build();

StartUp.cs文件修改如下:

        public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot(); var authenticationProviderKey = "qka_api";
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(authenticationProviderKey, options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "UserApi";
}); services.AddCors(options =>
{
options.AddPolicy("default", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("default");
app.UseOcelot().Wait();
}

Ocelot.js配置文件如下:

{
"ReRoutes": [
{
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"ServiceName": "userapi", //consul中的userapi的service名称
"LoadBalancer": "RoundRobin", //负载均衡算法
"UseServiceDiscovery": true, //启用服务发现
"UpstreamPathTemplate": "/{url}",
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "qka_api",
"AllowedScopes": []
}
},
{
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"ServiceName": "identityserverapi", //consul中的userapi的service名称
"LoadBalancer": "RoundRobin", //负载均衡算法
"UseServiceDiscovery": true, //启用服务发现
"UpstreamPathTemplate": "/{url}",
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:9000",
"ServiceDiscoveryProvider": {
"Host": "192.168.2.144",//consul的地址
"Port": 8500//consul的端口
}
}
}

asp.net core自带的基于角色授权需要像下图那样写死角色的名称,当角色权限发生变化时,需要修改并重新发布站点,很不方便。

所以我自定义了一个filter,实现角色授权验证:

public class UserPermissionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.Filters.Any(item => item is IAllowAnonymousFilter))
{
return;
}
if (!(context.ActionDescriptor is ControllerActionDescriptor))
{
return;
} var attributeList = new List<object>();
attributeList.AddRange((context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.GetCustomAttributes(true));
attributeList.AddRange((context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.DeclaringType.GetCustomAttributes(true)); var authorizeAttributes = attributeList.OfType<UserPermissionFilterAttribute>().ToList();
if (!authorizeAttributes.Any())
{
return;
} var sub = context.HttpContext.Request.Headers["sub"];
string path = context.HttpContext.Request.Path.Value.ToLower();
string httpMethod = context.HttpContext.Request.Method.ToLower(); /*todo:
从数据库中根据role获取权限是否具有访问当前path和method的权限,
因调用频繁,
可考虑将角色权限缓存到redis中*/
bool isAuthorized = true;
if (!isAuthorized)
{
context.Result = new UnauthorizedResult();
return;
}
}
}

在需要授权的Action或Controller上加上该特性即可。

.net core使用Ocelot+Identity Server统一网关验证的更多相关文章

  1. (10)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- Ocelot+Identity Server

    用 JWT 机制实现验证的原理如下图:  认证服务器负责颁发 Token(相当于 JWT 值)和校验 Token 的合法性. 一. 相关概念 API 资源(API Resource):微博服务器接口. ...

  2. Asp.net core 学习笔记 ( identity server 4 JWT Part )

    更新 : id4 使用这个 DbContext 哦 dotnet ef migrations add identity-server-init --context PersistedGrantDbCo ...

  3. Asp.Net Core: Swagger 与 Identity Server 4

    Swagger不用多说,可以自动生成Web Api的接口文档和客户端调用代码,方便开发人员进行测试.通常我们只需要几行代码就可以实现这个功能: ... builder.Services.AddSwag ...

  4. 使用PostMan Canary测试受Identity Server 4保护的Web Api

    在<Asp.Net Core: Swagger 与 Identity Server 4>一文中介绍了如何生成受保护的Web Api的Swagger文档,本文介绍使用PostMan Cana ...

  5. .NET Core微服务之基于Ocelot+IdentityServer实现统一验证与授权

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构总览 这里,假设我们有两个客户端(一个Web网站,一个移动App),他们要使用系统,需要通过API网关(这里API网关始终作为 ...

  6. .net core Ocelot Consul 实现API网关 服务注册 服务发现 负载均衡

    大神张善友 分享过一篇 <.NET Core 在腾讯财付通的企业级应用开发实践>里面就是用.net core 和 Ocelot搭建的可扩展的高性能Api网关. Ocelot(http:// ...

  7. 系统集成之用户统一登录( LDAP + wso2 Identity Server)

    本文场景: LDAP + wso2 Identity Server + asp.net声明感知 场景 ,假定读者已经了解过ws-*协议族,及 ws-trust 和 ws-federation. 随着开 ...

  8. 从头编写asp.net core 2.0 web api 基础框架 (5) + 使用Identity Server 4建立Authorization Server (7) 可运行前后台源码

    前台使用angular 5, 后台是asp.net core 2.0 web api + identity server 4. 从头编写asp.net core 2.0 web api 基础框架: 第 ...

  9. ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)

    GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...

随机推荐

  1. OVS+DPDK Datapath 包分类技术

    本文主体内容译于[DPDK社区文档],但并没有逐字翻译,在原文的基础上进行了一些调整,增加了对TSS分类器的详细阐述. 1. 概览 本文描述了OVS+DPDK中的包分类器(datapath class ...

  2. c#调用野狗云 rest api

    野狗云就不多介绍了,这里主要是记录一下c#调用他们提供的rest api,把数据post到野狗云存储,直接上代码 static void Main(string[] args) { string st ...

  3. python的logging模块之读取yaml配置文件。

    python的logging模块是用来记录应用程序的日志的.关于logging模块的介绍,我这里不赘述,请参见其他资料.这里主要讲讲如何来读取yaml配置文件进行定制化的日志输出. python要读取 ...

  4. 新知识:JQuery语法基础与操作

     jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架).jQuery设计的宗旨是"write ...

  5. DHCP的主要知识点

    首先,先写一遍配置 好几种安装方式,我这里用的最简单的yum源安装: mkdir /mnt/cdrom mount -r /dev/sr0 /mnt/cdrom       ##创建挂载点 vim / ...

  6. Tomcat中常见线程说明

    http://blog.csdn.NET/jeff_fangji/article/details/41786205 本文讲述了Tomcat的常见线程的功能.名称.线程池和配置等信息,其中源码来自于To ...

  7. Cocos2d-x 实战

    跨平台商业项目实战:攻城大作战游戏创意触发点:做什么样的游戏?分析当前主流的游戏:经典游戏(俄罗斯方块).大众化的游戏(卡牌游戏.休闲游戏).重口味游戏. 游戏创意:生活当中 游戏开发流程:1.策划方 ...

  8. Gradle连接Maven仓库直接从仓库 更新JAR包

    一般情况下服务器编写好服务程序  会用Maven打成JAR包,放在Maven仓库里管理,我们在用的时候直接引用就可以, 那么如何在Gradle项目中使用本地的  或者远程的Maven仓库呢    当M ...

  9. Runc 简介

    RunC 是什么? RunC 是一个轻量级的工具,它是用来运行容器的,只用来做这一件事,并且这一件事要做好.我们可以认为它就是个命令行小工具,可以不用通过 docker 引擎,直接运行容器.事实上,r ...

  10. Docker 多主机网络总结(非常全)

    PS:文章首发公众号,欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 上篇文章介绍了容器网络的单主机网络,本文将进一步介绍多 ...