.net core使用Ocelot+Identity Server统一网关验证
源码下载地址:下载
项目结构如下图:
在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统一网关验证的更多相关文章
- (10)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- Ocelot+Identity Server
用 JWT 机制实现验证的原理如下图: 认证服务器负责颁发 Token(相当于 JWT 值)和校验 Token 的合法性. 一. 相关概念 API 资源(API Resource):微博服务器接口. ...
- Asp.net core 学习笔记 ( identity server 4 JWT Part )
更新 : id4 使用这个 DbContext 哦 dotnet ef migrations add identity-server-init --context PersistedGrantDbCo ...
- Asp.Net Core: Swagger 与 Identity Server 4
Swagger不用多说,可以自动生成Web Api的接口文档和客户端调用代码,方便开发人员进行测试.通常我们只需要几行代码就可以实现这个功能: ... builder.Services.AddSwag ...
- 使用PostMan Canary测试受Identity Server 4保护的Web Api
在<Asp.Net Core: Swagger 与 Identity Server 4>一文中介绍了如何生成受保护的Web Api的Swagger文档,本文介绍使用PostMan Cana ...
- .NET Core微服务之基于Ocelot+IdentityServer实现统一验证与授权
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构总览 这里,假设我们有两个客户端(一个Web网站,一个移动App),他们要使用系统,需要通过API网关(这里API网关始终作为 ...
- .net core Ocelot Consul 实现API网关 服务注册 服务发现 负载均衡
大神张善友 分享过一篇 <.NET Core 在腾讯财付通的企业级应用开发实践>里面就是用.net core 和 Ocelot搭建的可扩展的高性能Api网关. Ocelot(http:// ...
- 系统集成之用户统一登录( LDAP + wso2 Identity Server)
本文场景: LDAP + wso2 Identity Server + asp.net声明感知 场景 ,假定读者已经了解过ws-*协议族,及 ws-trust 和 ws-federation. 随着开 ...
- 从头编写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 基础框架: 第 ...
- ASP.NET Core Web API 索引 (更新Identity Server 4 视频教程)
GraphQL 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上) 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下) [视频] 使用ASP.NET C ...
随机推荐
- Nginx常用模块安装命令
将目录切换至Nginx安装包目录下,使用./configure命令进行安装.一些第三方模块需要先下载过来,指定下解压后的目录即可. ./configure --prefix=/usr/local/ng ...
- 移动web前端开发时注意事项(转)
在智能手机横行的时代,作为一个web前端,不会编写移动web界面,的确是件悲催的事情.当公司准备做一个微信的微网站时,作为一个多年经验的web前端码农,我迷茫了,真心不知道从何下手. 接下来就是搜一堆 ...
- rcp perspective 添加9个视图均匀排列
PageLayout布局方法 pageLayout.addView("NodePMTSStream" + ":1", IPageLayout.TOP, 0.5f ...
- 数据库面试题目- ORACLE
Posted on 2009-06-08 17:38 漠北的天空 阅读(110) 评论(0) 编辑 收藏 1. 列举几种表连接方式 Answer:等连接(内连接).非等连接.自连接.外连 ...
- 教你一步步发布一个开源库到 JCenter
今天想来分享下,如何一步步自己发布一个开源库到 JCenter 这方面的博客网上已经特别多了,所以本篇并不打算仅仅只是记录流程步骤而已,而是尽可能讲清楚,为什么需要有这个步骤,让大伙知其然的同时还知其 ...
- Django开发环境静态文件访问配置
settings主要配置项目: STATIC_ROOT = 'D:\Dev\jpDev\czxg\assets' #这个地方是所在系统标准目录文法配置 STATIC_URL = '/static/' ...
- HashMap原理浅析
HashMap概述 HashMap是基于哈希表和Map实现来的,它提供所有可选的映射方式,可以允许使用null键,除了不同步和允许使用null键之外,HashMap和HashTable基本上相同.因此 ...
- Python Tips阅读摘要
发现了一本关于Python精通知识点的好书<Python Tips>,关于Python的进阶的技巧.摘录一些比较有价值的内容作为分享. *args and **kwargs 在函数定义的时 ...
- python笔记:#014#综合应用
综合应用 -- 名片管理系统 目标 综合应用已经学习过的知识点: 变量 流程控制 函数 模块 开发 名片管理系统 系统需求 程序启动,显示名片管理系统欢迎界面,并显示功能菜单 ************ ...
- Nginx负载均衡和反向代理
1:反向代理 代理就是中介,那有反向代理就有正向代理,两者的区别是什么嘞? 正向代理隐藏真实客户端,服务端不知道实际发起请求的客户端.,proxy和client同属一个LAN,对server透明: 反 ...