|
|
|
@ -2,6 +2,7 @@ using Hangfire;
|
|
|
|
|
using Hangfire.MemoryStorage;
|
|
|
|
|
using Infrastructure.Data;
|
|
|
|
|
using Infrastructure.Events;
|
|
|
|
|
using Infrastructure.Extensions;
|
|
|
|
|
using Infrastructure.Jwt;
|
|
|
|
|
using Infrastructure.Office;
|
|
|
|
|
using Infrastructure.Security;
|
|
|
|
@ -10,6 +11,7 @@ using Infrastructure.Web.Authentication.Cookies;
|
|
|
|
|
using Infrastructure.Web.Mvc.ModelBinding.Metadata;
|
|
|
|
|
using Infrastructure.Web.SignalR;
|
|
|
|
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
|
|
|
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
|
|
|
using Microsoft.AspNetCore.Builder;
|
|
|
|
|
using Microsoft.AspNetCore.Hosting;
|
|
|
|
|
using Microsoft.AspNetCore.Http.Features;
|
|
|
|
@ -26,13 +28,17 @@ using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
|
using Microsoft.OpenApi.Models;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Serialization;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Security.Claims;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.Encodings.Web;
|
|
|
|
|
using System.Text.Unicode;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
@ -174,27 +180,60 @@ namespace Infrastructure.Web
|
|
|
|
|
|
|
|
|
|
public virtual void AddAuthentication(IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
|
|
|
|
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, opts =>
|
|
|
|
|
services.AddAuthentication(x =>
|
|
|
|
|
{
|
|
|
|
|
opts.Cookie.Name = this.GetType().FullName;
|
|
|
|
|
opts.LoginPath = "/Account/Login";
|
|
|
|
|
opts.LogoutPath = "/Account/Logout";
|
|
|
|
|
opts.AccessDeniedPath = "/Account/AccessDenied";
|
|
|
|
|
//不配置SessionStore则存储到cookie
|
|
|
|
|
var useCookieSessionStore = this._cfg.GetSection("AppSettings").GetValue<bool>("UseCookieSessionStore");
|
|
|
|
|
if (!useCookieSessionStore)
|
|
|
|
|
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
|
|
|
|
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
|
|
|
|
})
|
|
|
|
|
.AddJwtBearer(o =>
|
|
|
|
|
{
|
|
|
|
|
o.TokenValidationParameters = new TokenValidationParameters
|
|
|
|
|
{
|
|
|
|
|
opts.SessionStore = services.BuildServiceProvider().GetService<ITicketStore>();
|
|
|
|
|
}
|
|
|
|
|
opts.Events = new CookieAuthenticationEvents
|
|
|
|
|
ValidateIssuerSigningKey = true,
|
|
|
|
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_cfg["jwt:key"])),
|
|
|
|
|
ValidateIssuer = false,
|
|
|
|
|
ValidIssuer = _cfg["jwt:issuer"],
|
|
|
|
|
ValidateAudience = false,
|
|
|
|
|
ValidAudience = _cfg["jwt:audience"]
|
|
|
|
|
};
|
|
|
|
|
o.Events = new JwtBearerEvents
|
|
|
|
|
{
|
|
|
|
|
//OnRedirectToLogin = RedirectToLogin(),
|
|
|
|
|
OnValidatePrincipal = ValidatePrincipal
|
|
|
|
|
OnTokenValidated = TokenValidated,
|
|
|
|
|
OnForbidden = OnForbidden,
|
|
|
|
|
OnAuthenticationFailed = OnAuthenticationFailed,
|
|
|
|
|
OnChallenge = context =>
|
|
|
|
|
{
|
|
|
|
|
if (!context.Request.IsAjax())
|
|
|
|
|
{
|
|
|
|
|
context.Response.Redirect("/Account/Login");
|
|
|
|
|
context.HandleResponse();
|
|
|
|
|
}
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
},
|
|
|
|
|
OnMessageReceived = context =>
|
|
|
|
|
{
|
|
|
|
|
if (context.Request.Cookies.Keys.Contains("jwt"))
|
|
|
|
|
{
|
|
|
|
|
context.Token = context.Request.Cookies["jwt"];
|
|
|
|
|
}
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
o.SecurityTokenValidators.Clear();
|
|
|
|
|
o.SecurityTokenValidators.Insert(0, new InvalidTokenValidator());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Task OnAuthenticationFailed(AuthenticationFailedContext arg)
|
|
|
|
|
{
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Task OnForbidden(ForbiddenContext arg)
|
|
|
|
|
{
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual void AddSwagger(IServiceCollection services)
|
|
|
|
|
{
|
|
|
|
|
services.AddSwaggerGen(c =>
|
|
|
|
@ -319,5 +358,44 @@ namespace Infrastructure.Web
|
|
|
|
|
{
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual Task TokenValidated(TokenValidatedContext arg)
|
|
|
|
|
{
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal class InvalidTokenValidator : ISecurityTokenValidator
|
|
|
|
|
{
|
|
|
|
|
public InvalidTokenValidator()
|
|
|
|
|
{
|
|
|
|
|
ExceptionType = typeof(SecurityTokenException);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public InvalidTokenValidator(Type exceptionType)
|
|
|
|
|
{
|
|
|
|
|
ExceptionType = exceptionType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Type ExceptionType { get; set; }
|
|
|
|
|
|
|
|
|
|
public bool CanValidateToken => true;
|
|
|
|
|
|
|
|
|
|
public int MaximumTokenSizeInBytes
|
|
|
|
|
{
|
|
|
|
|
get { throw new NotImplementedException(); }
|
|
|
|
|
set { throw new NotImplementedException(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool CanReadToken(string securityToken) => true;
|
|
|
|
|
|
|
|
|
|
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
|
|
|
|
|
{
|
|
|
|
|
var constructor = ExceptionType.GetTypeInfo().GetConstructor(new[] { typeof(string) });
|
|
|
|
|
var exception = (Exception)constructor.Invoke(new[] { ExceptionType.Name });
|
|
|
|
|
var token = new JwtSecurityTokenHandler().ReadJwtToken(securityToken);
|
|
|
|
|
validatedToken = token;
|
|
|
|
|
return new ClaimsPrincipal(new ClaimsIdentity(token.Claims, JwtBearerDefaults.AuthenticationScheme, "Name", "Role"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|