GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

——出自 https://graphql.cn

由于HotChocklate是是基于asp.net core框架,所以授权策略与原生的asp.net core mvc项目大同小异,都是通过固定角色,自定义策略等方式来进行的。下面的例子就是通过一个自定义策略的例子来进行的。

并且授权是在实体类和实体类的属性上的,而不是像之前在Controller的Action上,对应的是一个api的url。

看实例了解详情:

添加Nuget包

HotChocolate.AspNetCore

HotChocolate.Data

HotChocolate.Data.EntityFramework

HotChocolate.AspNetCore.Authorization

权限类

namespace GraphQLDemo02
{/// <summary>/// 用户或角色或其他凭据实体/// </summary>public class Permission{/// <summary>/// 用户或角色或其他凭据名称/// </summary>public virtual string Name{ get; set; }/// <summary>/// 请求Url/// </summary>public virtual string Url{ get; set; }}
}

创建自定义策略处理类

using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;
using System;namespace GraphQLDemo02
{/// <summary>/// 权限授权Handler/// </summary>public class PermissionHandler : AuthorizationHandler<PermissionRequirement>{/// <summary>/// 验证权限/// </summary>/// <param name="context"></param>/// <param name="requirement"></param>/// <returns></returns>protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{//这里可以过滤属性授权Console.WriteLine(context.Resource.GetType().GetProperty("Path").GetValue(context.Resource));//是否经过验证var isAuthenticated = context?.User?.Identity?.IsAuthenticated;if (isAuthenticated.HasValue && isAuthenticated.Value){context.Succeed(requirement);}else{context.Fail();}return Task.CompletedTask;}}
}

AuthorizationRequirement类

using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using System;namespace GraphQLDemo02
{/// <summary>/// 必要参数类/// </summary>public class PermissionRequirement : IAuthorizationRequirement{ /// <summary>/// 认证授权类型/// </summary>public string ClaimType { internal get; set; }/// <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">拒约请求的url</param>/// <param name="permissions">权限集合</param>/// <param name="claimType">声明类型</param>/// <param name="issuer">发行人</param>/// <param name="audience">订阅人</param>/// <param name="signingCredentials">签名验证实体</param>public PermissionRequirement(string claimType, string issuer, string audience, SigningCredentials signingCredentials, TimeSpan expiration){ClaimType = claimType;                Issuer = issuer;Audience = audience;Expiration = expiration;SigningCredentials = signingCredentials;}}
}

Token生成类

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;namespace GraphQLDemo02
{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 response = new{Status = true,access_token = encodedJwt,expires_in = permissionRequirement.Expiration.TotalMilliseconds,token_type = "Bearer"};return response;}}
}

Starup.cs

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Security.Claims;
using System.Text;
using Microsoft.EntityFrameworkCore;namespace GraphQLDemo02
{public class Startup{public IConfiguration Configuration { get; }public Startup(IConfiguration configuration){Configuration = configuration;}public void ConfigureServices(IServiceCollection services){          services.AddPooledDbContextFactory<AdventureWorks2016Context>((services, options) => options.UseSqlServer(Configuration.GetConnectionString("ConnectionString")).UseLoggerFactory(services.GetRequiredService<ILoggerFactory>())).AddGraphQLServer().AddAuthorization().AddQueryType<Query>().AddFiltering().AddSorting().AddProjections();AddAuth(services);}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseAuthentication();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapGraphQL();});}void AddAuth(IServiceCollection services){//读取配置文件var audienceConfig = Configuration.GetSection("Audience");var symmetricKeyAsBase64 = audienceConfig["Secret"];var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);var signingKey = new SymmetricSecurityKey(keyByteArray);var tokenValidationParameters = new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = signingKey,ValidateIssuer = true,ValidIssuer = audienceConfig["Issuer"],ValidateAudience = true,ValidAudience = audienceConfig["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(              ClaimTypes.Role,audienceConfig["Issuer"],audienceConfig["Audience"],signingCredentials,expiration: TimeSpan.FromSeconds(1000000)//设置Token过期时间);services.AddAuthorization(options =>{options.AddPolicy("Permission", policy => policy.AddRequirements(permissionRequirement));}).AddAuthentication(options =>{options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o =>{//不使用httpso.RequireHttpsMetadata = false;o.TokenValidationParameters = tokenValidationParameters;});//注入授权Handlerservices.AddSingleton<IAuthorizationHandler, PermissionHandler>();services.AddSingleton(permissionRequirement);}}
}

Query.cs

using HotChocolate;
using HotChocolate.Data;
using HotChocolate.Types;
using System;
using System.Linq;
using System.Security.Claims;namespace GraphQLDemo02
{       public class Query{[UseDbContext(typeof(AdventureWorks2016Context))][UseOffsetPaging][UseProjection][UseFiltering][UseSorting]public IQueryable<Product> GetProducts([ScopedService] AdventureWorks2016Context context){return context.Products;}[UseDbContext(typeof(AdventureWorks2016Context))][UsePaging][UseProjection][UseFiltering][UseSorting]public IQueryable<Person> GetPersons([ScopedService] AdventureWorks2016Context context){return context.People;}public TokenModel Login(string username, string password, [Service] PermissionRequirement requirement){Console.WriteLine(username);var isValidated = username == "gsw" && password == "111111";if (!isValidated){return new TokenModel(){Result = false,Message = "认证失败"};}else{//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色var claims = new Claim[] {new Claim(ClaimTypes.Name, username),new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(200000).ToString())};var token = JwtToken.BuildJwtToken(claims, requirement);return new TokenModel(){Result = true,Data = token.access_token};}}    }
}

HotChocklate的验证是通过在实体类或实体类的属性上加自定义策略来对数据进行权限控制,所以下面的例子是加在实体类上,全部属性进行授权验证。

Product.cs

    [HotChocolate.AspNetCore.Authorization.Authorize(Policy = "Permission")]public partial class Product{//此处略n多行}

Person.cs

    [Authorize(Policy = "Permission")]public partial class Person{//此处略n多行}

运行结果:

未验证

登录

拿到token后,在header上追加验证token信息,再次访问,成功获取数据

GraphQL:验证与授权相关推荐

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

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

  2. Authentication vs. Authorization 验证与授权[整理]

    Authentication vs. Authorization 验证与授权 Authentication vs. Authorization 验证与授权 It is important to cla ...

  3. asp.net2.0安全性(3)--验证与授权

    "验证"与"授权"是对网页资源安全管理的两道门. 验证(Authentication):检查用户是否是合法的用户.就像是网站大门口的保卫,服责验证使用的用户名和 ...

  4. iis授权mysql验证_ASP.NET Web API身份验证和授权

    本文是作者所理解和翻译的内容. 这篇文章包括两部分:身份验证和授权. 身份验证用来确定一个用户的身份.例如,Alice用她的用户名和密码登陆系统,服务器用她的用户名和密码来确定她的身份. 授权是判断一 ...

  5. 01_Weblogic课程之概念篇:代理服务器,web服务器,应用程序服务器,JNDI概念,JTA概念,Java消息服务,Java验证和授权(JAAS),Java管理扩展,Web客户机,客户机应用程序

     1 什么是服务器 Weblogic中服务器分为两种,一种是受管服务器,另外一种是管理服务器. Weblogic课程(Weblogic是Oracle公司的,最开始的是BEA公司的) 一 系统管理 ...

  6. ASP.NET Web API身份验证和授权

    英语原文地址:http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-a ...

  7. .NET6之MiniAPI(十):基于策略的身份验证和授权

    JWT不管是基于角色,还是自定义策略,实现的步骤都是大同小异的,基于自定义策略的步骤如下: 1.appsettings.json中配置JWT参 2.添加身份认证和授权服务和中间件,并设置为策略模式和策 ...

  8. .NET6之MiniAPI(九):基于角色的身份验证和授权

    身份验证是这样一个过程:由用户提供凭据,然后将其与存储在操作系统.数据库.应用或资源中的凭据进行比较. 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作. 授权指判断允许用户执行 ...

  9. asp.net core2.2 多用户验证和授权

    asp.net core2.2 用户验证 和授权有很详细和特贴心的介绍,我感兴趣的主要是这两篇: cookie身份验证 基于角色的授权 我的项目有两类用户: 微信公众号用户,用户名为公众号的openi ...

  10. 开源软件加密授权方案_身份验证和授权作为开源解决方案服务

    开源软件加密授权方案 通过实施身份验证和授权(a&a)机制为所有用户数据设计集中式服务. 我将分享我的经验并最终确定解决方案的结论. 该设计包括客户端(Web应用程序)和服务器(A&A ...

最新文章

  1. 时间序列数据的存储和计算 - 开源时序数据库解析
  2. matlab能控型模型,级倒立摆MATLAB仿真、能控能观性分析、数学模型、极点配置
  3. 【SICP练习】57 练习2.27
  4. java内部类练习题,学习笔记——Java内部类练习题
  5. scrapy crawlspider
  6. 机器学习 —— 极大似然估计与条件概率
  7. ffmpeg 源代码简单分析 : avcodec_decode_video2()
  8. Output Arcade for Mac:集合大量 Loop 素材的素材库插件
  9. 漫谈 Clustering (番外篇): Dimensionality Reduction
  10. 机器学习基础 集成学习进阶(XGBoost+LightGBM)
  11. 图片格式tif转换jpg
  12. 声纹识别demo_声纹识别 · 科大讯飞MSC开发指南-iOS · 看云
  13. 深入 WEP和 WPA密码原理
  14. 性能测试——性能监控工具——nmon文件的打开与分析
  15. [C语言]函数(function)
  16. android 采集音频输出,Android系统分析之Audio音频流, 音频策略, 输出设备之间的关系...
  17. 用计算机计算告白密码,阿拉伯数字高级表白密码 很火的表白密码
  18. kickstart自动化系统安装_利用Kickstart自动化安装CentOS的教程
  19. MAX40026 280ps高速比较器开发资料原理图源代码
  20. Java 处理那种无法解析的json数组

热门文章

  1. php框架之laravel
  2. python 垃圾回收详解
  3. MVC-控制器向View传值的三种方法
  4. IIS相关问题及解决方案
  5. CSS/DIV网页设计视频教程目录【转】
  6. 如何在Google文档中的图片周围换行
  7. 使用iOS 4越狱iPhone或iPod Touch
  8. python实现异步的几种方式_终于搞明白了,异步Python比同步Python究竟快在哪里?...
  9. Cocos Creator Ui系统
  10. 中兴智能视觉大数据:人脸识别技术目前处于“用的不够,用的不好”