From 60b30ce5427a8aee3daed4f1fec5ef899316a934 Mon Sep 17 00:00:00 2001 From: pavelbannov Date: Fri, 17 May 2019 11:32:23 +0300 Subject: [PATCH] Replace Singletons with DI. Added support for working with db. Added first version of CookieAuthHandler. Added PeopleController for test auth. --- common/ASC.Common/ASC.Common.csproj | 3 + common/ASC.Common/Data/DbManager.cs | 3 +- common/ASC.Common/Data/DbRegistry.cs | 60 ++++++--- .../Security/Cryptography/InstanceCrypto.cs | 22 ++-- .../Cryptography/MachinePseudoKeys.cs | 17 +-- common/ASC.Common/Utils/Signature.cs | 22 ++-- common/ASC.Core.Common/ASC.Core.Common.csproj | 1 - .../ConnectionStringNameTypeConverter.cs | 22 ++-- common/ASC.Core.Common/Context/CoreContext.cs | 13 +- .../Context/SecurityContext.cs | 35 ++--- common/ASC.Core.Common/HostedSolution.cs | 3 +- .../MultiRegionHostedSolution.cs | 3 +- .../Security/Authentication/CookieStorage.cs | 13 +- .../Tests/CookieStorageTest.cs | 2 +- common/ASC.Core.Common/Tests/SignatureTest.cs | 2 +- web/ASC.Web.Api/ASC.Web.Api.csproj | 7 +- .../Controllers/PeopleController.cs | 20 +++ web/ASC.Web.Api/Handlers/CookieAuthHandler.cs | 43 +++++++ web/ASC.Web.Api/Startup.cs | 120 ++++++++++-------- web/ASC.Web.Api/appsettings.json | 20 ++- 20 files changed, 289 insertions(+), 142 deletions(-) create mode 100644 web/ASC.Web.Api/Controllers/PeopleController.cs create mode 100644 web/ASC.Web.Api/Handlers/CookieAuthHandler.cs diff --git a/common/ASC.Common/ASC.Common.csproj b/common/ASC.Common/ASC.Common.csproj index 4aa5262518..14d149ef19 100644 --- a/common/ASC.Common/ASC.Common.csproj +++ b/common/ASC.Common/ASC.Common.csproj @@ -47,8 +47,11 @@ + + + diff --git a/common/ASC.Common/Data/DbManager.cs b/common/ASC.Common/Data/DbManager.cs index e4022d33dd..a6c23b288a 100644 --- a/common/ASC.Common/Data/DbManager.cs +++ b/common/ASC.Common/Data/DbManager.cs @@ -84,7 +84,8 @@ namespace ASC.Common.Data { get { return Command.Connection; } } - + + DbRegistry DbRegistry { get => (DbRegistry)HttpContext.Current.RequestServices.GetService(typeof(DbRegistry)); } public DbManager(string databaseId, int? commandTimeout = null) : this(databaseId, true, commandTimeout) diff --git a/common/ASC.Common/Data/DbRegistry.cs b/common/ASC.Common/Data/DbRegistry.cs index 4c1b2a855d..46c69bf12b 100644 --- a/common/ASC.Common/Data/DbRegistry.cs +++ b/common/ASC.Common/Data/DbRegistry.cs @@ -31,10 +31,19 @@ using System.Data; using System.Data.Common; using ASC.Common.Data.Sql; using ASC.Common.Data.Sql.Dialects; - +using Microsoft.Extensions.Configuration; + namespace ASC.Common.Data -{ - public static class DbRegistry +{ + public class DbProviderFactoryCustom + { + public string Name { get; set; } + public string Invariant { get; set; } + public string Description { get; set; } + public string Type { get; set; } + } + + public class DbRegistry { private const string DEFAULT = "DEFAULT"; private static readonly object syncRoot = new object(); @@ -42,14 +51,17 @@ namespace ASC.Common.Data private static readonly IDictionary connnectionStrings = new Dictionary(StringComparer.InvariantCultureIgnoreCase); private static readonly IDictionary dialects = new Dictionary(StringComparer.InvariantCultureIgnoreCase); private static volatile bool configured = false; + + protected IConfiguration Configuration { get; set; } - static DbRegistry() - { + public DbRegistry(IConfiguration configuration) + { + Configuration = configuration; dialects["MySql.Data.MySqlClient.MySqlClientFactory"] = new MySQLDialect(); dialects["System.Data.SQLite.SQLiteFactory"] = new SQLiteDialect(); } - internal static void RegisterDatabase(string databaseId, DbProviderFactory providerFactory, string connectionString) + internal void RegisterDatabase(string databaseId, DbProviderFactory providerFactory, string connectionString) { if (string.IsNullOrEmpty(databaseId)) throw new ArgumentNullException("databaseId"); if (providerFactory == null) throw new ArgumentNullException("providerFactory"); @@ -70,17 +82,17 @@ namespace ASC.Common.Data } } - internal static void RegisterDatabase(string databaseId, string providerInvariantName, string connectionString) + internal void RegisterDatabase(string databaseId, string providerInvariantName, string connectionString) { RegisterDatabase(databaseId, DbProviderFactories.GetFactory(providerInvariantName), connectionString); } - public static void RegisterDatabase(string databaseId, ConnectionStringSettings connectionString) + public void RegisterDatabase(string databaseId, ConnectionStringSettings connectionString) { RegisterDatabase(databaseId, connectionString.ProviderName, connectionString.ConnectionString); } - public static void UnRegisterDatabase(string databaseId) + public void UnRegisterDatabase(string databaseId) { if (string.IsNullOrEmpty(databaseId)) throw new ArgumentNullException("databaseId"); @@ -107,7 +119,7 @@ namespace ASC.Common.Data } } - public static bool IsDatabaseRegistered(string databaseId) + public bool IsDatabaseRegistered(string databaseId) { lock (syncRoot) { @@ -115,7 +127,7 @@ namespace ASC.Common.Data } } - public static DbConnection CreateDbConnection(string databaseId) + public DbConnection CreateDbConnection(string databaseId) { Configure(); @@ -132,7 +144,7 @@ namespace ASC.Common.Data return connection; } - public static DbProviderFactory GetDbProviderFactory(string databaseId) + public DbProviderFactory GetDbProviderFactory(string databaseId) { Configure(); @@ -143,7 +155,7 @@ namespace ASC.Common.Data return providers.ContainsKey(databaseId) ? providers[databaseId] : null; } - public static ConnectionStringSettings GetConnectionString(string databaseId) + public ConnectionStringSettings GetConnectionString(string databaseId) { Configure(); @@ -154,7 +166,7 @@ namespace ASC.Common.Data return connnectionStrings.ContainsKey(databaseId) ? new ConnectionStringSettings(databaseId, connnectionStrings[databaseId], providers[databaseId].GetType().Name) : null; } - public static ISqlDialect GetSqlDialect(string databaseId) + public ISqlDialect GetSqlDialect(string databaseId) { var provider = GetDbProviderFactory(databaseId); if (provider != null && dialects.ContainsKey(provider.GetType().FullName)) @@ -165,18 +177,30 @@ namespace ASC.Common.Data } - public static void Configure() + public void Configure() { if (!configured) { lock (syncRoot) { if (!configured) - { + { + var dbProviderFactories = Configuration.GetSection("DbProviderFactories"); + + foreach (var ch in dbProviderFactories.GetChildren()) + { + var cs = new DbProviderFactoryCustom(); + ch.Bind(cs); + DbProviderFactories.RegisterFactory(cs.Invariant, cs.Type); + } + + var connectionStrings = Configuration.GetSection("ConnectionStrings"); var factories = DbProviderFactories.GetFactoryClasses(); AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory); //SQLite - foreach (ConnectionStringSettings cs in ConfigurationManager.ConnectionStrings) - { + foreach (var ch in connectionStrings.GetChildren()) + { + var cs = new ConnectionStringSettings(); + ch.Bind(cs); var factory = factories.Rows.Find(cs.ProviderName); if (factory == null) { diff --git a/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs b/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs index dd49a3d496..a00045ffdb 100644 --- a/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs +++ b/common/ASC.Common/Security/Cryptography/InstanceCrypto.cs @@ -35,16 +35,20 @@ using System.Text; namespace ASC.Security.Cryptography { - public static class InstanceCrypto - { - public static string Encrypt(string data) + public class InstanceCrypto + { + protected MachinePseudoKeys MachinePseudoKeys { get; set; } + + public InstanceCrypto(MachinePseudoKeys machinePseudoKeys) => MachinePseudoKeys = machinePseudoKeys; + + public string Encrypt(string data) { return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(data))); } - public static byte[] Encrypt(byte[] data) + public byte[] Encrypt(byte[] data) { - Rijndael hasher = Rijndael.Create(); + var hasher = Rijndael.Create(); hasher.Key = EKey(); hasher.IV = new byte[hasher.BlockSize >> 3]; using (var ms = new MemoryStream()) @@ -57,14 +61,14 @@ namespace ASC.Security.Cryptography } } - public static string Decrypt(string data) + public string Decrypt(string data) { return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(data))); } - public static byte[] Decrypt(byte[] data) + public byte[] Decrypt(byte[] data) { - Rijndael hasher = Rijndael.Create(); + var hasher = Rijndael.Create(); hasher.Key = EKey(); hasher.IV = new byte[hasher.BlockSize >> 3]; @@ -80,7 +84,7 @@ namespace ASC.Security.Cryptography } } - private static byte[] EKey() + private byte[] EKey() { return MachinePseudoKeys.GetMachineConstant(32); } diff --git a/common/ASC.Common/Security/Cryptography/MachinePseudoKeys.cs b/common/ASC.Common/Security/Cryptography/MachinePseudoKeys.cs index 1e14a96ada..481a95c5cc 100644 --- a/common/ASC.Common/Security/Cryptography/MachinePseudoKeys.cs +++ b/common/ASC.Common/Security/Cryptography/MachinePseudoKeys.cs @@ -30,20 +30,21 @@ using System.IO; using System.Linq; using System.Text; using ASC.Common.Security; - +using Microsoft.Extensions.Configuration; + namespace ASC.Security.Cryptography { - public static class MachinePseudoKeys + public class MachinePseudoKeys { - private static readonly byte[] confkey = null; + private byte[] confkey = null; - static MachinePseudoKeys() + public MachinePseudoKeys(IConfiguration configuration) { - var key = ConfigurationManager.AppSettings["core.machinekey"]; + var key = configuration["core:machinekey"]; if (string.IsNullOrEmpty(key)) { - key = ConfigurationManager.AppSettings["asc.common.machinekey"]; + key = configuration["asc:common.machinekey"]; } if (!string.IsNullOrEmpty(key)) { @@ -52,7 +53,7 @@ namespace ASC.Security.Cryptography } - public static byte[] GetMachineConstant() + public byte[] GetMachineConstant() { if (confkey != null) { @@ -64,7 +65,7 @@ namespace ASC.Security.Cryptography return BitConverter.GetBytes(fi.CreationTime.ToOADate()); } - public static byte[] GetMachineConstant(int bytesCount) + public byte[] GetMachineConstant(int bytesCount) { var cnst = Enumerable.Repeat(0, sizeof (int)).Concat(GetMachineConstant()).ToArray(); var icnst = BitConverter.ToInt32(cnst, cnst.Length - sizeof (int)); diff --git a/common/ASC.Common/Utils/Signature.cs b/common/ASC.Common/Utils/Signature.cs index 8f3eacbc5a..44126fe064 100644 --- a/common/ASC.Common/Utils/Signature.cs +++ b/common/ASC.Common/Utils/Signature.cs @@ -35,14 +35,16 @@ using Microsoft.AspNetCore.WebUtilities; namespace ASC.Common.Utils { - public static class Signature - { - public static string Create(T obj) + public class Signature + { + protected MachinePseudoKeys MachinePseudoKeys { get; set; } + public Signature(MachinePseudoKeys machinePseudoKeys) => MachinePseudoKeys = machinePseudoKeys; + public string Create(T obj) { return Create(obj, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant())); } - public static string Create(T obj, string secret) + public string Create(T obj, string secret) { var serializer = new JavaScriptSerializer(); var str = serializer.Serialize(obj); @@ -50,17 +52,17 @@ namespace ASC.Common.Utils return WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(payload)); } - public static T Read(string signature) + public T Read(string signature) { return Read(signature, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant())); } - public static T Read(string signature, string secret) + public T Read(string signature, string secret) { return Read(signature, secret, true); } - public static T Read(string signature, string secret, bool useSecret) + public T Read(string signature, string secret, bool useSecret) { try { @@ -76,15 +78,15 @@ namespace ASC.Common.Utils catch (Exception) { } - return default(T); + return default; } - private static string GetHashBase64(string str) + private string GetHashBase64(string str) { return Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(str))); } - private static string GetHashBase64MD5(string str) + private string GetHashBase64MD5(string str) { return Convert.ToBase64String(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(str))); } diff --git a/common/ASC.Core.Common/ASC.Core.Common.csproj b/common/ASC.Core.Common/ASC.Core.Common.csproj index 3466c60e74..d0ee64d9c6 100644 --- a/common/ASC.Core.Common/ASC.Core.Common.csproj +++ b/common/ASC.Core.Common/ASC.Core.Common.csproj @@ -33,6 +33,5 @@ - \ No newline at end of file diff --git a/common/ASC.Core.Common/Configuration/ConnectionStringNameTypeConverter.cs b/common/ASC.Core.Common/Configuration/ConnectionStringNameTypeConverter.cs index 25ace0fc13..c1963e1c91 100644 --- a/common/ASC.Core.Common/Configuration/ConnectionStringNameTypeConverter.cs +++ b/common/ASC.Core.Common/Configuration/ConnectionStringNameTypeConverter.cs @@ -31,16 +31,16 @@ using System.Globalization; namespace ASC.Core.Configuration { - class ConnectionStringNameTypeConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string); - } + //class ConnectionStringNameTypeConverter : TypeConverter + //{ + // public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + // { + // return sourceType == typeof(string); + // } - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - return DbRegistry.GetConnectionString((string)value); - } - } + // public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + // { + // return DbRegistry.GetConnectionString((string)value); + // } + //} } diff --git a/common/ASC.Core.Common/Context/CoreContext.cs b/common/ASC.Core.Common/Context/CoreContext.cs index 90b2590d24..a5d16f090b 100644 --- a/common/ASC.Core.Common/Context/CoreContext.cs +++ b/common/ASC.Core.Common/Context/CoreContext.cs @@ -34,16 +34,19 @@ using ASC.Core.Data; namespace ASC.Core { - public static class CoreContext - { - static CoreContext() - { + public class CoreContext + { + public DbRegistry DbRegistry { get; set; } + public CoreContext(DbRegistry dbRegistry) + { + DbRegistry = dbRegistry; ConfigureCoreContextByDefault(); } public static CoreConfiguration Configuration { get; private set; } + public TenantManager TenantManager1 => TenantManager; public static TenantManager TenantManager { get; private set; } public static UserManager UserManager { get; private set; } @@ -69,7 +72,7 @@ namespace ASC.Core } } - private static void ConfigureCoreContextByDefault() + private void ConfigureCoreContextByDefault() { var cs = DbRegistry.GetConnectionString("core"); if (cs == null) diff --git a/common/ASC.Core.Common/Context/SecurityContext.cs b/common/ASC.Core.Common/Context/SecurityContext.cs index c0db56f49e..a0d89bc4e5 100644 --- a/common/ASC.Core.Common/Context/SecurityContext.cs +++ b/common/ASC.Core.Common/Context/SecurityContext.cs @@ -36,18 +36,17 @@ using ASC.Common.Logging; using ASC.Common.Security; using ASC.Common.Security.Authentication; using ASC.Common.Security.Authorizing; -using ASC.Common.Web; using ASC.Core.Billing; using ASC.Core.Security.Authentication; using ASC.Core.Security.Authorizing; using ASC.Core.Tenants; using ASC.Core.Users; using ASC.Security.Cryptography; -using Microsoft.AspNetCore.Http.Features; - +using Microsoft.Extensions.Configuration; + namespace ASC.Core { - public static class SecurityContext + public class SecurityContext { private static readonly ILog log = LogManager.GetLogger("ASC.Core"); @@ -64,15 +63,21 @@ namespace ASC.Core public static IPermissionResolver PermissionResolver { get; private set; } + protected IConfiguration configuration { get; set; } + protected CookieStorage cookieStorage { get; set; } + protected CoreContext CoreContext { get; set; } + + public SecurityContext(IConfiguration configuration, CookieStorage cookieStorage, CoreContext coreContext) + { + this.configuration = configuration; + this.cookieStorage = cookieStorage; + CoreContext = coreContext; - static SecurityContext() - { var azManager = new AzManager(new RoleProvider(), new PermissionProvider()); PermissionResolver = new PermissionResolver(azManager); - } + } - - public static string AuthenticateMe(string login, string password) + public string AuthenticateMe(string login, string password) { if (login == null) throw new ArgumentNullException("login"); if (password == null) throw new ArgumentNullException("password"); @@ -83,7 +88,7 @@ namespace ASC.Core return AuthenticateMe(new UserAccount(u, tenantid)); } - public static bool AuthenticateMe(string cookie) + public bool AuthenticateMe(string cookie) { if (!string.IsNullOrEmpty(cookie)) { @@ -107,9 +112,9 @@ namespace ASC.Core } log.InfoFormat("Empty Bearer cookie: {0} {1}", ipFrom, address); } - else if (CookieStorage.DecryptCookie(cookie, out tenant, out userid, out login, out password, out indexTenant, out expire, out indexUser)) + else if (cookieStorage.DecryptCookie(cookie, out tenant, out userid, out login, out password, out indexTenant, out expire, out indexUser)) { - if (tenant != CoreContext.TenantManager.GetCurrentTenant().TenantId) + if (tenant != CoreContext.TenantManager1.GetCurrentTenant().TenantId) { return false; } @@ -175,7 +180,7 @@ namespace ASC.Core return false; } - public static string AuthenticateMe(IAccount account) + public string AuthenticateMe(IAccount account) { if (account == null || account.Equals(Configuration.Constants.Guest)) throw new InvalidCredentialException("account"); @@ -215,7 +220,7 @@ namespace ASC.Core roles.Add(Role.Users); account = new UserAccount(u, CoreContext.TenantManager.GetCurrentTenant().TenantId); - cookie = CookieStorage.EncryptCookie(CoreContext.TenantManager.GetCurrentTenant().TenantId, account.ID); + cookie = cookieStorage.EncryptCookie(CoreContext.TenantManager.GetCurrentTenant().TenantId, account.ID); } Principal = new GenericPrincipal(account, roles.ToArray()); @@ -223,7 +228,7 @@ namespace ASC.Core return cookie; } - public static string AuthenticateMe(Guid userId) + public string AuthenticateMe(Guid userId) { return AuthenticateMe(CoreContext.Authentication.GetAccountByID(userId)); } diff --git a/common/ASC.Core.Common/HostedSolution.cs b/common/ASC.Core.Common/HostedSolution.cs index e7be2a6127..083c861276 100644 --- a/common/ASC.Core.Common/HostedSolution.cs +++ b/common/ASC.Core.Common/HostedSolution.cs @@ -58,7 +58,8 @@ namespace ASC.Core get; private set; } - + + public CookieStorage CookieStorage { get; set; } public HostedSolution(ConnectionStringSettings connectionString) : this(connectionString, null) diff --git a/common/ASC.Core.Common/MultiRegionHostedSolution.cs b/common/ASC.Core.Common/MultiRegionHostedSolution.cs index abb550bc2f..5b583bc4fc 100644 --- a/common/ASC.Core.Common/MultiRegionHostedSolution.cs +++ b/common/ASC.Core.Common/MultiRegionHostedSolution.cs @@ -43,7 +43,8 @@ namespace ASC.Core private readonly Dictionary regions = new Dictionary(); private readonly String dbid; private volatile bool initialized = false; - + + DbRegistry DbRegistry { get; set; } public MultiRegionHostedSolution(string dbid) { diff --git a/common/ASC.Core.Common/Security/Authentication/CookieStorage.cs b/common/ASC.Core.Common/Security/Authentication/CookieStorage.cs index 5ca19f6a6c..ebeafcfc46 100644 --- a/common/ASC.Core.Common/Security/Authentication/CookieStorage.cs +++ b/common/ASC.Core.Common/Security/Authentication/CookieStorage.cs @@ -35,11 +35,14 @@ using ASC.Common.Web; namespace ASC.Core.Security.Authentication { - class CookieStorage + public class CookieStorage { private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss,fff"; + protected InstanceCrypto InstanceCrypto { get; set; } + + public CookieStorage(InstanceCrypto instanceCrypto) => InstanceCrypto = instanceCrypto; - public static bool DecryptCookie(string cookie, out int tenant, out Guid userid, out string login, out string password, out int indexTenant, out DateTime expire, out int indexUser) + public bool DecryptCookie(string cookie, out int tenant, out Guid userid, out string login, out string password, out int indexTenant, out DateTime expire, out int indexUser) { tenant = Tenant.DEFAULT_TENANT; userid = Guid.Empty; @@ -78,7 +81,7 @@ namespace ASC.Core.Security.Authentication } - public static string EncryptCookie(int tenant, Guid userid, string login = null, string password = null) + public string EncryptCookie(int tenant, Guid userid, string login = null, string password = null) { var settingsTenant = TenantCookieSettings.GetForTenant(tenant); var expires = TenantCookieSettings.GetExpiresTime(tenant); @@ -86,7 +89,7 @@ namespace ASC.Core.Security.Authentication return EncryptCookie(tenant, userid, login, password, settingsTenant.Index, expires, settingsUser.Index); } - public static string EncryptCookie(int tenant, Guid userid, string login, string password, int indexTenant, DateTime expires, int indexUser) + public string EncryptCookie(int tenant, Guid userid, string login, string password, int indexTenant, DateTime expires, int indexUser) { var s = string.Format("{0}${1}${2}${3}${4}${5}${6}${7}", (login ?? string.Empty).ToLowerInvariant(), @@ -102,7 +105,7 @@ namespace ASC.Core.Security.Authentication } - private static string GetUserDepenencySalt() + private string GetUserDepenencySalt() { var data = string.Empty; try diff --git a/common/ASC.Core.Common/Tests/CookieStorageTest.cs b/common/ASC.Core.Common/Tests/CookieStorageTest.cs index e1f4ff71f9..d153ceaf87 100644 --- a/common/ASC.Core.Common/Tests/CookieStorageTest.cs +++ b/common/ASC.Core.Common/Tests/CookieStorageTest.cs @@ -35,7 +35,7 @@ namespace ASC.Core.Common.Tests public class CookieStorageTest { [TestMethod] - public void Validate() + public void Validate(CookieStorage CookieStorage) { var t1 = 1; var id1 = Guid.NewGuid(); diff --git a/common/ASC.Core.Common/Tests/SignatureTest.cs b/common/ASC.Core.Common/Tests/SignatureTest.cs index 19ae3e9fb8..b986b95301 100644 --- a/common/ASC.Core.Common/Tests/SignatureTest.cs +++ b/common/ASC.Core.Common/Tests/SignatureTest.cs @@ -35,7 +35,7 @@ namespace ASC.Core.Common.Tests public class SignatureTest { [TestMethod] - public void TestSignature() + public void TestSignature(Signature Signature) { var validObject = new { expire = DateTime.UtcNow.AddMinutes(15), key = "345jhndfg", ip = "192.168.1.1" }; var encoded = Signature.Create(validObject, "ThE SeCret Key!"); diff --git a/web/ASC.Web.Api/ASC.Web.Api.csproj b/web/ASC.Web.Api/ASC.Web.Api.csproj index 8b182c5244..69f354f595 100644 --- a/web/ASC.Web.Api/ASC.Web.Api.csproj +++ b/web/ASC.Web.Api/ASC.Web.Api.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.0 @@ -15,4 +15,9 @@ + + + + + diff --git a/web/ASC.Web.Api/Controllers/PeopleController.cs b/web/ASC.Web.Api/Controllers/PeopleController.cs new file mode 100644 index 0000000000..c8d4a03cf9 --- /dev/null +++ b/web/ASC.Web.Api/Controllers/PeopleController.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; + +namespace ASC.Employee.Core.Controllers +{ + [FormatFilter] + [Route("api/2.0/[controller]")] + [ApiController] + [Authorize] + public class PeopleController : ControllerBase + { + // GET api/values + [HttpGet("{action}.{format?}")] + public ActionResult> Self() + { + return new string[] { "value1", "value2" }; + } + } +} diff --git a/web/ASC.Web.Api/Handlers/CookieAuthHandler.cs b/web/ASC.Web.Api/Handlers/CookieAuthHandler.cs new file mode 100644 index 0000000000..10e26543ec --- /dev/null +++ b/web/ASC.Web.Api/Handlers/CookieAuthHandler.cs @@ -0,0 +1,43 @@ +using System.Security.Claims; +using System.Text.Encodings.Web; +using System.Threading; +using System.Threading.Tasks; +using ASC.Core; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace ASC.Web.Api.Handlers +{ + public class CookieAuthHandler : AuthenticationHandler + { + protected SecurityContext SecurityContext { get; set; } + + protected IHttpContextAccessor HttpContextAccessor { get; set; } + + public CookieAuthHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) + { + } + + public CookieAuthHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, SecurityContext securityContext, IHttpContextAccessor httpContextAccessor) + : this(options, logger, encoder, clock) + { + SecurityContext = securityContext; + HttpContextAccessor = httpContextAccessor; + } + + protected override Task HandleAuthenticateAsync() + { + ASC.Common.HttpContext.Configure(HttpContextAccessor); + SecurityContext.AuthenticateMe(Context.Request.Cookies["asc_auth_key"]); + + return Task.FromResult( + AuthenticateResult.Success( + new AuthenticationTicket( + new ClaimsPrincipal(Thread.CurrentPrincipal), + new AuthenticationProperties(), + Scheme.Name))); + } + } +} diff --git a/web/ASC.Web.Api/Startup.cs b/web/ASC.Web.Api/Startup.cs index 09c77ef9ae..a8808f9dc8 100644 --- a/web/ASC.Web.Api/Startup.cs +++ b/web/ASC.Web.Api/Startup.cs @@ -1,53 +1,67 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace ASC.Web.Api -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddCors(); - - services.AddControllers() - .AddNewtonsoftJson(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseCors(builder => builder.AllowAnyOrigin()); - - app.UseRouting(); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -} +using ASC.Common.Data; +using ASC.Common.Utils; +using ASC.Core; +using ASC.Core.Security.Authentication; +using ASC.Security.Cryptography; +using ASC.Web.Api.Handlers; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace ASC.Web.Api +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddControllers() + .AddNewtonsoftJson() + .AddXmlSerializerFormatters(); + + services.AddHttpContextAccessor(); + + services.AddAuthentication("cookie") + .AddScheme("cookie", a=> { }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseCors(builder => builder.AllowAnyOrigin()); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git a/web/ASC.Web.Api/appsettings.json b/web/ASC.Web.Api/appsettings.json index d9d9a9bff6..126c902247 100644 --- a/web/ASC.Web.Api/appsettings.json +++ b/web/ASC.Web.Api/appsettings.json @@ -6,5 +6,23 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "core": { + "machinekey": "1123askdasjklasbnd" + }, + "ConnectionStrings": { + "default": { + "name": "default", + "connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none", + "providerName": "MySql.Data.MySqlClient" + } + }, + "DbProviderFactories": { + "mysql": { + "name": "MySQL Data Provider", + "invariant": "MySql.Data.MySqlClient", + "description": ".Net Framework Data Provider for MySQL", + "type": "MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data" + } + } }