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);
}
}
}