/// <summary>Authenticate for the specified authentication scheme.</summary> /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Http.HttpContext" />.</param> /// <param name="scheme">The name of the authentication scheme.</param> /// <returns>The result.</returns> public virtual async Task <AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme) { if (scheme == null) { var authenticateSchemeAsync = await Schemes.GetDefaultAuthenticateSchemeAsync(); scheme = authenticateSchemeAsync?.Name; if (scheme == null) { throw new InvalidOperationException("No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); } } var handlerAsync = await Handlers.GetHandlerAsync(context, scheme); if (handlerAsync == null) { throw new InvalidOperationException(string.Format("No authentication handler is configured to authenticate for the scheme: {0}", scheme)); } var result = await handlerAsync.AuthenticateAsync(); if (result != null && result.Succeeded) { return(AuthenticateResult.Success(new AuthenticationTicket(await(this).Transform.TransformAsync(result.Principal), result.Properties, result.Ticket.AuthenticationScheme))); } return(result); }
/// <summary> /// Authenticate for the specified authentication scheme. /// </summary> /// <param name="context">The <see cref="HttpContext"/>.</param> /// <param name="scheme">The name of the authentication scheme.</param> /// <returns>The result.</returns> public virtual async Task <AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme) { if (scheme == null) { var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync(); scheme = defaultScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingHandlerException(scheme); } var result = await handler.AuthenticateAsync(); if (result != null && result.Succeeded) { var transformed = await Transform.TransformAsync(result.Principal); return(AuthenticateResult.Success(new AuthenticationTicket(transformed, result.Properties, result.Ticket.AuthenticationScheme))); } return(result); }
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { ////赋值用户权限 Requirement = 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 (Requirement.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 (Requirement.Permissions.Where(w => w.Name == name && w.Url.ToLower() == questUrl).Count() <= 0) { //无权限跳转到拒绝页面 httpContext.Response.Redirect(requirement.DeniedAction); } } context.Succeed(requirement); return; } } //判断没有登录时,是否访问登录的url,并且是Post请求,并助是form表单提交类型,否则为失败 if (!questUrl.Equals(Requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType)) { //httpContext.Response.Redirect("/api/test"); context.Fail(); return; } context.Succeed(requirement); }
/// <summary> /// Authenticate for the specified authentication scheme. /// </summary> /// <param name="context">The <see cref="HttpContext"/>.</param> /// <param name="scheme">The name of the authentication scheme.</param> /// <returns>The result.</returns> public virtual async Task <AuthenticateResult> AuthenticateAsync(HttpContext context, string?scheme) { if (scheme == null) { var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync(); scheme = defaultScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions)."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingHandlerException(scheme); } // Handlers should not return null, but we'll be tolerant of null values for legacy reasons. var result = (await handler.AuthenticateAsync()) ?? AuthenticateResult.NoResult(); if (result.Succeeded) { var principal = result.Principal !; var doTransform = true; _transformCache ??= new HashSet <ClaimsPrincipal>(); if (_transformCache.Contains(principal)) { doTransform = false; } if (doTransform) { principal = await Transform.TransformAsync(principal); _transformCache.Add(principal); } return(AuthenticateResult.Success(new AuthenticationTicket(principal, result.Properties, result.Ticket !.AuthenticationScheme))); } return(result); }
// 重载异步处理程序 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { // 将最新的角色和接口列表更新 var data = await RoleModulePermissionServices.GetRoleModule(); var list = (from item in data where item.IsDeleted == false orderby item.Id select new PermissionItem { Url = item.Module?.LinkUrl, Role = item.Role?.Name, }).ToList(); requirement.Permissions = list; //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息 var filterContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext); var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)?.HttpContext; //请求Url if (httpContext != null) { var questUrl = httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口!" }); httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; filterContext.Result = new JsonResult(payload); context.Succeed(requirement); 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的判断,因为只需判断该角色下是否匹配当前URL即可,若不匹配都是无效请求 //var isMatchUrl = false; //var permisssionGroup = requirement.Permissions.GroupBy(g => g.Url); //foreach (var item in permisssionGroup) //{ // try // { // if (Regex.Match(questUrl, item.Key?.ObjToString().ToLower())?.Value == questUrl) // { // isMatchUrl = true; // break; // } // } // catch (Exception) // { // } //} //权限中是否存在请求的url //if (requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key?.ToLower() == questUrl).Count() > 0) //if (isMatchUrl) if (true) { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); var isMatchRole = false; var permisssionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role)); foreach (var item in permisssionRoles) { try { if (Regex.Match(questUrl, item.Url?.ObjToString().ToLower())?.Value == questUrl) { isMatchRole = true; break; } } catch (Exception) { // ignored } } //验证权限 //if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0) if (currentUserRoles.Count <= 0 || !isMatchRole) { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "403", Message = "很抱歉,您无权访问该接口!" }); httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; filterContext.Result = new JsonResult(payload); context.Succeed(requirement); return; // 可以在这里设置跳转页面,不过还是会访问当前接口地址的 //httpContext.Response.Redirect(requirement.DeniedAction); } } //else //{ // context.Fail(); // return; //} //判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口!" }); httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; filterContext.Result = new JsonResult(payload); context.Succeed(requirement); return; } return; } } //判断没有登录时,是否访问登录的url,并且是Post请求,并且是form表单提交类型,否则为失败 if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType)) { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口!" }); httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; filterContext.Result = new JsonResult(payload); } } context.Succeed(requirement); }
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { ////赋值用户权限 Requirement = requirement; //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息 AuthorizationFilterContext authorizationFilterContext = context.Resource as AuthorizationFilterContext; if (authorizationFilterContext != null) { var httpContext = 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()) { httpContext.Response.Redirect(requirement.DeniedAction); 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; var name = httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Name).Value; if (!Permissions.Any(g => g.UserName == name && g.Role?.Urls != null && g.Role.Urls.Any(w => w.Url.ToLower() == questUrl))) { //无权限跳转到拒绝页面 context.Fail(); 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); }
// 重写异步处理程序 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { /* * * 首先必须在 controller 上进行配置 Authorize ,可以策略授权,也可以角色等基本授权 * * 1、开启公约, startup 中的全局授权过滤公约:o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention()); * * 2、不开启公约,使用 IHttpContextAccessor ,也能实现效果; */ // 将最新的角色和接口列表更新 var data = await _roleModuleService.GetRoleModule(); var list = (from item in data orderby item.Id select new PermissionItem { Url = item.ModuleApi?.LinkUrl, Role = item.Role?.Name, }).ToList(); requirement.Permissions = list; //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息 //var filterContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext); var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)?.HttpContext; if (httpContext == null) { httpContext = _accessor.HttpContext; } //请求Url if (httpContext != null) { var questUrl = httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && 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 (true) { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); var isMatchRole = false; var permisssionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role)); foreach (var item in permisssionRoles) { try { if (Regex.Match(questUrl, item.Url?.ToLower())?.Value == questUrl) { isMatchRole = true; break; } } catch (Exception) { // ignored } } //验证权限 if (currentUserRoles.Count <= 0 || !isMatchRole) { context.Succeed(requirement); //测试验证权限临时通过 需要加上按钮管理才能控制 //context.Fail(); //return; } } //判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); return; } 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); }
/// <summary> /// 重载异步处理程序 /// </summary> /// <param name="context"></param> /// <param name="requirement"></param> /// <returns></returns> protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { // 将最新的角色和接口列表更新, // 注意这里我用到了AOP缓存,只是减少与数据库的访问次数,而又保证是最新的数据 var data = await _roleModulePermissionServices.GetRoleModule(); var list = (from item in data orderby item.Id select new Permission { Id = item.Id, ApiUrl = item.ApiUrl, RequestMethod = item.RequestMethod, ActionName = item.ActionName }).ToList(); requirement.Permissions = list; //从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 // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).FirstOrDefault(); //这里就是对权限的验证 //请求方式 httpContext.Request.Method //请求连接 questUrl //我们的权限 Permissions if (requirement.Permissions.Where(g => g.Id == currentUserRoles && g.ApiUrl?.ToLower() == questUrl && g.RequestMethod == httpContext.Request.Method).Count() <= 0) { context.Fail(); return; } //判断过期时间 if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); return; } 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); }
// 重载异步处理程序 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { // 将最新的角色和接口列表更新 var data = await _roleModulePermissionServices.GeRoleModule(); var list = (from item in data where item.IsDeleted == false orderby item.Id select new Permission { Url = item.Module?.LinkUrl, Role = item.Role?.Name, }).ToList(); requirement.Permissions = list; //从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 (requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key?.ToLower() == questUrl).Count() > 0) { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); //验证权限 if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0) { context.Fail(); return; // 可以在这里设置跳转页面,不过还是会访问当前接口地址的 httpContext.Response.Redirect(requirement.DeniedAction); } } else { context.Fail(); return; } //判断过期时间 if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); return; } 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); }
// 重写异步处理程序 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { /* * .netcore3.0 启用EndpointRouting后,权限filter不再添加到ActionDescriptor ,而将权限直接作为中间件运行, * 同时所有filter都会添加到endpoint.Metadata。因此,文中的 * context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext不再成立。 * * 解决方案有两个: * * 首先必须在 controller 上进行配置 Authorize ,可以策略授权,也可以角色等基本授权 * * 1、开启公约, startup 中的全局授权过滤公约:o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention()); * * 2、不开启公约,使用 IHttpContextAccessor ,也能实现效果,但是不能自定义返回格式,详细看下边配置; */ // 将最新的角色和接口列表更新 var data = await RoleModulePermissionServices.GetRoleModule(); var list = (from item in data where item.IsDeleted == false orderby item.Id select new PermissionItem { Url = item.Module?.LinkUrl, Role = item.Role?.Name, }).ToList(); requirement.Permissions = list; //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息 var filterContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext); var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)?.HttpContext; if (httpContext == null) { httpContext = _accessor.HttpContext; } //请求Url if (httpContext != null) { var questUrl = httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口,请确保已经登录!" }); httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; httpContext.Response.ContentType = "application/json"; await httpContext.Response.WriteAsync(payload); 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 (requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key?.ToLower() == questUrl).Count() > 0) //if (isMatchUrl) if (true) { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); var isMatchRole = false; var permisssionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role)); foreach (var item in permisssionRoles) { try { if (Regex.Match(questUrl, item.Url?.ObjToString().ToLower())?.Value == questUrl) { isMatchRole = true; break; } } catch (Exception) { // ignored } } //验证权限 //if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0) if (currentUserRoles.Count <= 0 || !isMatchRole) { // 可以在这里设置跳转页面 //context.Fail(); //return; var payload = JsonConvert.SerializeObject(new { Code = "403", Message = "很抱歉,您的访问权限等级不够,联系管理员!" }); httpContext.Response.StatusCode = StatusCodes.Status403Forbidden; httpContext.Response.ContentType = "application/json"; await httpContext.Response.WriteAsync(payload); return; } } //判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口,请确保已经登录!" }); httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; httpContext.Response.ContentType = "application/json"; await httpContext.Response.WriteAsync(payload); return; } return; } } //判断没有登录时,是否访问登录的url,并且是Post请求,并且是form表单提交类型,否则为失败 if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType)) { //context.Fail(); //return; //自定义返回数据 var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口,请确保已经登录!" }); httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized; httpContext.Response.ContentType = "application/json"; await httpContext.Response.WriteAsync(payload); return; } } context.Succeed(requirement); }
// 重载异步处理程序 protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { // 将最新的角色和权限列表更新 var data = await roleModulePermissionServices.GetPermission(); var list = (from item in data where item.S04_IsValid == 0 select new PermissionItem { Url = item.S03_BackRoute, RoleId = item.S02_RoleId, }).ToList(); requirement.Permissions = list; //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息 var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)?.HttpContext; //请求Url if (httpContext != null) { var questUrl = httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && 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; if (true) { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); var isMatchRole = false; var permisssionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.RoleId.ToString())); foreach (var item in permisssionRoles) { try { if (Regex.Match(questUrl, item.Url?.ToString().ToLower())?.Value == questUrl) { isMatchRole = true; break; } } catch (Exception) { // ignored } } //验证权限 //if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0) if (currentUserRoles.Count <= 0 || !isMatchRole) { context.Fail(); // 可以在这里设置跳转页面,不过还是会访问当前接口地址的 httpContext.Response.Redirect(requirement.DeniedAction); } } //else //{ // context.Fail(); // return; //} //判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); return; } 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); }
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { // 将最新的角色和接口列表更新 var data = await RoleModulePermissionService.GetRoleModule().ConfigureAwait(false); var list = (from item in data where item.IsDelete == false orderby item.Id select new PermissionItem { Url = item.Module?.LinkUrl, Role = item.Role?.RoleName, }).ToList(); requirement.Permissions = list; // 从AuthorizationHandlerContext转成HttpContext,以便取出表头信息 var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)?.HttpContext; // https://q.cnblogs.com/q/120091/ if (httpContext == null) { httpContext = _accessor.HttpContext; } // 请求Url if (httpContext != null) { var questUrl = httpContext.Request.Path.Value.ToLower(); // 判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync().ConfigureAwait(false)) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name).ConfigureAwait(false) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) { context.Fail(); return; } } // 判断请求是否拥有凭据,即有没有登录 var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync().ConfigureAwait(false); if (defaultAuthenticate != null) { var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name).ConfigureAwait(false); // result?.Principal不为空即登录成功 if (result?.Principal != null) { httpContext.User = result.Principal; // 权限中是否存在请求的url // if (requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key?.ToLower() == questUrl).Count() > 0) // if (isMatchUrl) if (true) { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); var isMatchRole = false; var permissionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role)); foreach (var item in permissionRoles) { try { if (Regex.Match(questUrl, item.Url?.ObjToString().ToLower())?.Value == questUrl) { isMatchRole = true; break; } } catch (Exception) { // ignored } } // 验证权限 // if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0) if (currentUserRoles.Count <= 0 || !isMatchRole) { context.Fail(); return; } } // 判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); return; } 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); }
/// <summary> /// 判断是否授权 /// </summary> /// <param name="context"></param> /// <param name="requirement"></param> /// <returns></returns> protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, MvcAuthorizeHandlerReq requirement) { #region 说明 /* * .netcore3.0 启用EndpointRouting后,权限filter不再添加到ActionDescriptor ,而将权限直接作为中间件运行, * 同时所有filter都会添加到endpoint.Metadata。因此,文中的 * context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext不再成立。 * * 解决方案有两个: * * 首先必须在 controller 上进行配置 Authorize ,可以策略授权,也可以角色等基本授权 * * 1、开启公约, startup 中的全局授权过滤公约:o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention()); * * 2、不开启公约,使用 IHttpContextAccessor ,也能实现效果,但是不能自定义返回格式,详细看下边配置; */ #endregion //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息(netcore2.2之前有效,3.0需要开启全局过滤公约才有这个上下文) var filterContext = (context.Resource as AuthorizationFilterContext); var httpContext = (context.Resource as AuthorizationFilterContext)?.HttpContext; if (httpContext == null) { httpContext = HttpContextAccessor.HttpContext; } //请求Url if (httpContext != null) { var user = httpContext.User; //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) { AuthDeal(context, requirement, httpContext, false); return; } } //判断请求是否拥有凭据,即有没有登录 var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name); if (result?.Principal != null) { httpContext.User = result.Principal; //判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { // todo:根据用户判断是否 有对应角色和路由的权限 //var questUrl = httpContext.Request.Path.Value.ToLower(); if (requirement.Roles != null && requirement.Roles.Length > 0) { var strReqRoles = string.Join(",", requirement.Roles.Select(x => ((int)x).ToString())); var isUserHadRoles = httpContext.User.IsInRole(strReqRoles); if (!isUserHadRoles) { AuthDeal(context, requirement, httpContext, false); return; } } if (true) { AuthDeal(context, requirement, httpContext, true); return; } } } } } AuthDeal(context, requirement, httpContext, false); return; }
/// <summary> /// 判断是否授权 /// </summary> /// <param name="context"></param> /// <param name="requirement"></param> /// <returns></returns> protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ApiAuthorizeHandlerReq requirement) { #region 说明 /* * .netcore3.0 启用EndpointRouting后,权限filter不再添加到ActionDescriptor ,而将权限直接作为中间件运行, * 同时所有filter都会添加到endpoint.Metadata。因此,文中的 * context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext不再成立。 * * 解决方案有两个: * * 首先必须在 controller 上进行配置 Authorize ,可以策略授权,也可以角色等基本授权 * * 1、开启公约, startup 中的全局授权过滤公约:o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention()); * * 2、不开启公约,使用 IHttpContextAccessor ,也能实现效果,但是不能自定义返回格式,详细看下边配置; */ #endregion //从AuthorizationHandlerContext转成HttpContext,以便取出表求信息(netcore2.2之前有效,3.0需要开启全局过滤公约才有这个上下文) var filterContext = (context.Resource as AuthorizationFilterContext); var httpContext = (context.Resource as AuthorizationFilterContext)?.HttpContext; if (httpContext == null) { httpContext = HttpContextAccessor.HttpContext; } //请求Url if (httpContext != null) { var user = httpContext.User; //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync()) { AuthDeal(context, requirement, httpContext, false); return; } } //判断请求是否拥有凭据,即有没有登录 var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync(); if (defaultAuthenticate != null) { #region 微软Jwt中间件已经实现了Authorzation的验证 //// jwt授权信息在Header //// 检测是否包含'Authorization'请求头 //var httpHeader = httpContext.Request.Headers; //if (httpHeader.ContainsKey("Authorization")) //{ // var tokenHeader = httpHeader["Authorization"].ToString().Replace("Bearer ", ""); // try // { // if (tokenHeader.Length >= 128) // { // // 解析jwt,获取用户信息,进行jwt授权登录 // var tokenInfo = JwtHelper.DecryptJwtToken(tokenHeader); // var claims = new List<Claim> // { // new Claim(JwtRegisteredClaimNames.Jti, tokenInfo.Uid.ToString()), // new Claim(ClaimTypes.Name,tokenInfo.UserName), // }; // claims.AddRange(tokenInfo.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s))); // // 保存用户信息到HttpContext.User // await JwtHelper.IdentifyLogin(claims); // // todo:根据角色判断是否有权限调用 // AuthDeal(context, requirement, httpContext, true); // return; // } // } // catch (Exception ex) // { // LogHelper.Error($"ApiAuthorizeHandler:解析Jwt失败:{ex.Message}", ex); // } //} #endregion var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name); if (result?.Principal != null) { httpContext.User = result.Principal; //判断过期时间(这里仅仅是最坏验证原则,你可以不要这个if else的判断,因为我们使用的官方验证,Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断) if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now) { AuthDeal(context, requirement, httpContext, true); return; } // todo:根据角色判断是否有权限调用 if (requirement.Roles != null && requirement.Roles.Length > 0) { var strReqRoles = string.Join(",", requirement.Roles.Select(x => ((int)x).ToString())); var isUserHadRoles = httpContext.User.IsInRole(strReqRoles); if (!isUserHadRoles) { AuthDeal(context, requirement, httpContext, false); return; } } } } } AuthDeal(context, requirement, httpContext, false); return; }
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PolicyRequirement requirement) { bool haspermission = false; //从AuthorizationHandlerContext转成HttpContext,以便取出表头信息 var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext; var pAttrs = (context.Resource as AuthorizationFilterContext).Filters.Where(e => (e as ParentPermissionAttribute) != null).ToList(); //请求Url var questUrl = httpContext.Request.Path.Value.ToLower(); //判断请求是否停止 var handlers = httpContext.RequestServices.GetRequiredService <IAuthenticationHandlerProvider>(); foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync()) { if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && 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 (requirement.Permissions.GroupBy(g => g.Path).Where(w => w.Key?.ToLower() == questUrl).Count() > 0) // { // 获取当前用户的角色信息 var currentUserRoles = (from item in httpContext.User.Claims where item.Type == requirement.ClaimType select item.Value).ToList(); // 获取当前用户的信息 var userinfo = Newtonsoft.Json.JsonConvert.DeserializeObject <Sys_UserDTO>((from item in httpContext.User.Claims where item.Type == "userinfo" select item.Value).FirstOrDefault()); //验证权限 foreach (ParentPermissionAttribute pattr in pAttrs) { if (await _service.ValidUserPermission(userinfo.PKID, pattr.Route, pattr.OperationType)) { haspermission = true; break; } } if (!haspermission) { context.Fail(); return; } //判断过期时间 if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == "exp")?.Value) != null && DateTimeHelper.ConvertToDateTime(httpContext.User.Claims.SingleOrDefault(s => s.Type == "exp")?.Value) >= DateTime.Now) { context.Succeed(requirement); } else { context.Fail(); return; } return; } } }