public static ICollection <PolicyRequirement> ScanEndpointsForPolicyRequirements(this HttpConfiguration config) { var explorer = new ApiExplorer(config); var endpoints = new List <PolicyRequirement>(); foreach (var description in explorer.ApiDescriptions) { var action = description.ActionDescriptor; var endpoint = new PolicyRequirement { HttpMethod = description.HttpMethod.Method, Controller = description.ActionDescriptor.ControllerDescriptor.ControllerName, Action = description.ActionDescriptor.ActionName, EndpointPath = $"/{description.RelativePath}" }; var pipeline = action.GetFilterPipeline(); foreach (var filter in pipeline.OfType <PolicyAttribute>()) { endpoint.Policies.Add(filter.PolicyType.Name); } endpoints.Add(endpoint); } return(endpoints); }
/// <summary> /// 授权处理 /// </summary> /// <param name="context"></param> /// <param name="requirement"></param> /// <param name="resource">基于资源的授权</param> /// <returns></returns> protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PolicyRequirement requirement /*, IDocument resource */) { var httpContext = _httpContextAccessor.HttpContext; //获取授权方式 var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { //验证签发的用户信息 var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name); if (result.Succeeded) { //判断是否为已停用的token if (!await _jwtApp.IsCurrentActiveTokenAsync()) { context.Fail(); return; } httpContext.User = result.Principal; //判断是否过期 if (DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration).Value) < DateTime.UtcNow) { context.Fail(); } //判断角色 //var url = httpContext.Request.Path.Value.ToLower(); var role = httpContext.User.Claims.Where(c => c.Type == ClaimTypes.Role).FirstOrDefault().Value;; if (context.User.IsInRole("admin")) { context.Succeed(requirement); } else { //允许任何人创建或读取资源 if (requirement == Operations.Create || requirement == Operations.Read) { context.Succeed(requirement); } else { //只有资源的创建者才可以修改和删除 if (context.User.Identity.Name == "admin")//resource.Creator) { context.Succeed(requirement); } else { context.Fail(); } } } return; } } context.Fail(); }
// This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { //添加cors 服务 配置跨域处理 services.AddCors(options => { options.AddPolicy("any", cors => { cors.AllowAnyOrigin() //允许任何来源的主机访问 .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials();//指定处理cookie }); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1) //序列化设置 .AddJsonOptions(options => { //不使用驼峰样式的key //options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //设置时间格式 options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; }); //添加AutoMapper支持 services.AddAutoMapper(typeof(AutoMapperConfig)); //添加IP获取 services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); #region JWT配置 var jwtSetting = new JwtSetting(); //Configuration.Bind("JwtSetting", jwtSetting); //services // .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) // .AddJwtBearer(options => // { // options.TokenValidationParameters = new TokenValidationParameters // { // ValidIssuer = jwtSetting.Issuer, // ValidAudience = jwtSetting.Audience, // IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.Secret)), // // 默认允许 300s 的时间偏移量,设置为0 // ClockSkew = TimeSpan.Zero // }; // }); // 令牌验证参数,之前我们都是写在AddJwtBearer里的,这里提出来了 var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSetting.Secret)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var tokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, //验证发行人的签名密钥 IssuerSigningKey = key, ValidateIssuer = true, //验证发行人 ValidIssuer = jwtSetting.Issuer, //发行人 ValidateAudience = true, //验证订阅人 ValidAudience = jwtSetting.Audience, //订阅人 ValidateLifetime = true, //验证生命周期 ClockSkew = TimeSpan.Zero, //这个是定义的过期的缓存时间 RequireExpirationTime = true, //是否要求过期 }; var permission = new List <Sys_Menu>(); // 角色与接口的权限要求参数 var permissionRequirement = new PolicyRequirement( "/api/denied", // 拒绝授权的跳转地址(目前无用) permission, //这里还记得么,就是我们上边说到的角色地址信息凭据实体类 Permission ClaimTypes.Role, //基于角色的授权 jwtSetting.Issuer, //发行人 jwtSetting.Audience, //订阅人 //signingCredentials,//签名凭据 expiration: TimeSpan.FromSeconds(60 * 2) //接口的过期时间,注意这里没有了缓冲时间,你也可以自定义,在上边的TokenValidationParameters的 ClockSkew ); // ① 核心之一,配置授权服务,也就是具体的规则,已经对应的权限策略,比如公司不同权限的门禁卡 services.AddAuthorization(options => { options.AddPolicy("Client", policy => policy.RequireRole("Client").Build()); options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build()); options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System")); // 自定义基于策略的授权权限 options.AddPolicy("Permission", policy => policy.Requirements.Add(permissionRequirement)); }) // ② 核心之二,必需要配置认证服务,这里是jwtBearer默认认证,比如光有卡没用,得能识别他们 .AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) // ③ 核心之三,针对JWT的配置,比如门禁是如何识别的,是放射卡,还是磁卡 .AddJwtBearer(o => { o.TokenValidationParameters = tokenValidationParameters; }); // 依赖注入,将自定义的授权处理器 匹配给官方授权处理器接口,这样当系统处理授权的时候,就会直接访问我们自定义的授权处理器了。 services.AddSingleton <IAuthorizationHandler, PermissionHandler>(); // 将授权必要类注入生命周期内 services.AddSingleton(permissionRequirement); #endregion #region 依赖注入 //return RegisterAutofac(services);//注册Autofac var builder = new ContainerBuilder();//实例化容器 //注册所有模块module builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly()); //获取所有的程序集 //var assemblys = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray(); var assemblys = RuntimeHelper.GetAllAssemblies().ToArray(); //注册所有继承IDependency接口的类 builder.RegisterAssemblyTypes().Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.IsAbstract); //注册仓储,所有IRepository接口到Repository的映射 builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Repository") && !t.Name.StartsWith("I")).AsImplementedInterfaces(); //注册服务,所有IApplicationService到ApplicationService的映射 builder.RegisterAssemblyTypes(assemblys).Where(t => t.Name.EndsWith("Service") && !t.Name.StartsWith("I")).AsImplementedInterfaces(); builder.Populate(services); var ApplicationContainer = builder.Build(); return(new AutofacServiceProvider(ApplicationContainer)); //第三方IOC接管 core内置DI容器 //return services.BuilderInterceptableServiceProvider(builder => builder.SetDynamicProxyFactory()); #endregion }