using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Net.Http.Headers; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; using XYY.Common.Standard; using XYY.Core.Standard.Data.Infrastructure; using XYY.Model.Standard; using XYY.Service.Standard.UserService; namespace XYY.Authentication.Standard { public static class BasicAuthenticationScheme { public const string DefaultScheme = "Basic"; } public class BasicAuthenticationOption : AuthenticationSchemeOptions { } /// /// API服务中间证 /// 认证token /// public class BasicAuthenticationHandler : AuthenticationHandler { private readonly BasicAuthenticationOption authOptions; private readonly IUserService userService; private readonly IUnitOfWork unitOfWork; public BasicAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IUserService userService, IUnitOfWork unitOfWork) : base(options, logger, encoder, clock) { authOptions = options.CurrentValue; this.userService = userService; this.unitOfWork = unitOfWork; } public Endpoint GetEndpoint(HttpContext context) { if (context == null) { return null; } return context.Features.Get()?.Endpoint; } /// /// 认证 Token /// /// protected override async Task HandleAuthenticateAsync() { bool isAllow = false; var endpoint = GetEndpoint(this.Context); if (endpoint != null) { var allow = endpoint.Metadata.GetMetadata(); if (allow != null) { isAllow = true; } } else { var claims = new[] { new Claim(ClaimTypes.StreetAddress,""), }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); unitOfWork.CurrentName = ""; return await Task.FromResult(AuthenticateResult.Success(ticket)); } if (isAllow || Request.Path.Value.Contains("dingtalk") || Request.Path.Value.Contains("SendNowCustomerQuotaion", StringComparison.InvariantCultureIgnoreCase)) { var claims = new[] { new Claim(ClaimTypes.StreetAddress,""), }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); unitOfWork.CurrentName = ""; return await Task.FromResult(AuthenticateResult.Success(ticket)); } if (!Request.Headers.ContainsKey("Authorization")) { if (string.IsNullOrEmpty(Request.Query["access_token"])) { return AuthenticateResult.Fail("Missing Authorization "); } } try { string token = ""; //var uservice = Context.RequestServices.GetService(); if (Request.Headers.ContainsKey("Authorization")) { var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); //var credentialBytes = Convert.FromBase64String(authHeader.Parameter); if (!authHeader.Scheme.Equals("token", StringComparison.InvariantCultureIgnoreCase) && !authHeader.Scheme.Equals("bearer", StringComparison.InvariantCultureIgnoreCase)) { return AuthenticateResult.Fail("Invalid Token"); } else { token = authHeader.Parameter; } } else { token = Request.Query["access_token"]; } var user = await Authorized(token); if (user != null) { ///当前用户的身份信息 var claims = new[] { new Claim(ClaimTypes.StreetAddress,token), new Claim(ClaimTypes.NameIdentifier,user.Id.ToString()), new Claim(ClaimTypes.Name,user.NiceName), new Claim(ClaimTypes.GroupSid,user.CustomerId.ToString()), new Claim(ClaimTypes.Role,string.Join(",",user.Roles)), new Claim(ClaimTypes.AuthorizationDecision,string.Join(",",user.PrivilegeUrl)) }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); unitOfWork.CurrentName = user.NiceName; return await Task.FromResult(AuthenticateResult.Success(ticket)); } else { return AuthenticateResult.Fail("token无效"); } } catch { return AuthenticateResult.Fail("Invalid Authorization Header"); } } /// /// 质询 /// /// /// protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { //Response.Headers["WWW-Authenticate"] = $"Basic realm=our site"; await base.HandleChallengeAsync(properties); } /// /// 认证失败 /// /// /// protected override async Task HandleForbiddenAsync(AuthenticationProperties properties) { await base.HandleForbiddenAsync(properties); } private async Task Authorized(string token) { var ui = await userService.GetUserContentAtApi(token); return ui; } } public static class BasicAuthentication { public static void UseBasicAuthentication(this IApplicationBuilder app) { app.UseMiddleware(); } } public class BasicAuthenticationMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public BasicAuthenticationMiddleware(RequestDelegate next, ILoggerFactory LoggerFactory) { _next = next; _logger = LoggerFactory.CreateLogger(); } public async Task Invoke(HttpContext httpContext, IAuthenticationService authenticationService) { var authenticated = await authenticationService.AuthenticateAsync(httpContext, BasicAuthenticationScheme.DefaultScheme); //authenticated.Principal.Claims. //_logger.LogInformation("Access Status:" + authenticated.Succeeded); if (!authenticated.Succeeded) { await authenticationService.ForbidAsync(httpContext, BasicAuthenticationScheme.DefaultScheme, new AuthenticationProperties { }); return; } await _next(httpContext); } } }