黄贺彬 6 anni fa
parent
commit
6dac60ceac

+ 1 - 1
HaBookCms.Admin/Controllers/Sys/UsersController.cs

@@ -14,7 +14,7 @@ using System.Threading.Tasks;
 namespace HaBookCms.Admin.Controllers.Sys
 {
     /// <summary>
-    /// Blog控制器所有接口
+    ///  控制器所有接口
     /// </summary>
     [Authorize(Policy = "RequireAdmin")]
     [Produces("application/json")]

+ 86 - 0
HaBookCms.Contest/Controllers/UsersController.cs

@@ -0,0 +1,86 @@
+using HaBookCms.Admin.Models;
+using HaBookCms.Common.CryptHelper;
+using HaBookCms.Jwt.Model;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+
+namespace HaBookCms.Contest.Controllers
+{
+    /// <summary>
+    ///  控制器所有接口
+    /// </summary>
+    [Authorize(Policy = "ContestWeb")]
+    [Produces("application/json")]
+    [Route("api/Users")]
+    [ApiController]
+    public class UsersController : Controller
+    {
+        PermissionRequirement _requirement;
+        /// <summary>
+        /// 获取JWT的方法 3.0
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="pass"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [Route("checkLogin")]
+        [EnableCors("any")]
+        [AllowAnonymous]
+        public async Task<object> checkLogin(TicketInfo ticketInfo)
+        {
+
+
+            string jwtStr = string.Empty;
+            bool suc = false;
+
+            //  var user = await sysUserInfoServices.GetUserRoleNameStr(name, pass);
+            var user = "aaa";
+            if (user != null)
+            {
+                //如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
+                var claims = new List<Claim> {
+                    new Claim(ClaimTypes.Name, ticketInfo.teamModelId),
+                    new Claim(ClaimTypes.MobilePhone,""),
+                    new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
+                claims.AddRange(user.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
+
+                //用户标识
+                var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
+                identity.AddClaims(claims);
+
+                var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
+                return new JsonResult(token);
+            }
+            else
+            {
+                return new JsonResult(new
+                {
+                    Status = false,
+                    Message = "认证失败"
+                });
+            }
+        }
+
+        private int CheckTicketInfo(TicketInfo ticketInfo)
+        {
+            if (ticketInfo != null
+                && !string.IsNullOrEmpty(ticketInfo.sign)
+                && !string.IsNullOrEmpty(ticketInfo.ticket)
+                && !string.IsNullOrEmpty(ticketInfo.teamModelId))
+            {
+                string md5info = Md5Crypt.GetMd5String(ticketInfo.ticket);
+                if (md5info.Equals(ticketInfo.sign))
+                {
+                }
+            }
+            return 0;
+        }
+    }
+}

+ 9 - 0
HaBookCms.Contest/HaBookCms.Contest.csproj

@@ -11,4 +11,13 @@
     <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
   </ItemGroup>
 
+
+  <ItemGroup>
+    <ProjectReference Include="..\HaBookCms.Admin\HaBookCms.Admin.csproj" />
+    <ProjectReference Include="..\HaBookCms.Common\HaBookCms.Common.csproj" />
+    <ProjectReference Include="..\HaBookCms.ContextConfig\HaBookCms.ContextConfig.csproj" />
+    <ProjectReference Include="..\HaBookCms.Jwt\HaBookCms.Jwt.csproj" />
+    <ProjectReference Include="..\HaBookCms.RedisStorage\HaBookCms.RedisStorage.csproj" />
+  </ItemGroup>
+
 </Project>

+ 176 - 6
HaBookCms.Contest/Startup.cs

@@ -1,22 +1,49 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
+using System.IO;
+using System.Security.Claims;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Text.Unicode;
+using HaBookCms.Common.LogHelper;
+using HaBookCms.ContextConfig.Exceptions;
+using HaBookCms.Jwt.Filter;
+using HaBookCms.Jwt.Model;
+using HaBookCms.RedisStorage.Cache;
+using log4net;
+using log4net.Config;
+using log4net.Repository;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.HttpsPolicy;
+using Microsoft.AspNetCore.HttpOverrides;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
+using Microsoft.IdentityModel.Tokens;
 
 namespace HaBookCms.Contest
 {
     public class Startup
     {
-        public Startup(IConfiguration configuration)
+        /// <summary>
+        /// log4net 仓储库
+        /// </summary>
+        public static ILoggerRepository repository { get; set; }
+
+        public Startup(IConfiguration configuration, IHostingEnvironment env)
         {
             Configuration = configuration;
+            var builder = new ConfigurationBuilder()
+                .SetBasePath(env.ContentRootPath)
+                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
+            this.Configuration = builder.Build();
+            //log4net
+            repository = LogManager.CreateRepository("HaBookCms");
+            //指定配置文件
+            XmlConfigurator.Configure(repository, new FileInfo("Log4net.config"));
+            BaseConfigModel.SetBaseConfig(Configuration, env.ContentRootPath, env.WebRootPath);
         }
 
         public IConfiguration Configuration { get; }
@@ -33,6 +60,125 @@ namespace HaBookCms.Contest
 
 
             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+            //解决视图输出内容中文编码问题
+            services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));
+            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
+            #region 认证
+            JwtAuthConfigModel jwtConfig = new JwtAuthConfigModel();
+            // services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
+            //.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
+            // {
+            //     o.LoginPath = new PathString("/api/Users/checkLogin");
+            // })
+            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+             .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o =>
+             {
+
+                 o.TokenValidationParameters = new TokenValidationParameters
+                 {
+                     ValidIssuer = jwtConfig.Issuer,
+                     ValidAudience = jwtConfig.Audience,
+                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtConfig.JWTSecretKey)),
+
+                     /***********************************TokenValidationParameters的参数默认值***********************************/
+                     RequireSignedTokens = true,
+                     // SaveSigninToken = false,
+                     // ValidateActor = false,
+                     // 将下面两个参数设置为false,可以不验证Issuer和Audience,但是不建议这样做。
+                     ValidateAudience = true,
+                     ValidateIssuer = true,
+                     ValidateIssuerSigningKey = true,
+                     // 是否要求Token的Claims中必须包含 Expires
+                     RequireExpirationTime = true,
+                     // 允许的服务器时间偏移量
+                     // ClockSkew = TimeSpan.FromSeconds(300),
+                     ClockSkew = TimeSpan.Zero,
+                     // 是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比
+                     ValidateLifetime = true
+                 };
+             });
+            #endregion
+            var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtConfig.JWTSecretKey)), SecurityAlgorithms.HmacSha256);
+            // 如果要数据库动态绑定,这里先留个空,后边处理器里动态赋值
+            var permission = new List<Permission>();
+
+            // 角色与接口的权限要求参数
+            var permissionRequirement = new PermissionRequirement(
+                "/api/denied",// 拒绝授权的跳转地址(目前无用)
+                permission,
+                ClaimTypes.Role,//基于角色的授权
+                jwtConfig.Issuer,//发行人
+                jwtConfig.Audience,//听众
+                signingCredentials,//签名凭据
+                expiration: TimeSpan.FromSeconds(60 * 2)//接口的过期时间
+                );
+
+            #region 授权
+            services.AddAuthorization(options =>
+            {
+                options.AddPolicy("RequireApp", policy => policy.RequireRole("App").Build());
+                options.AddPolicy("RequireAdmin", policy => policy.RequireRole("Admin").Build());
+                options.AddPolicy("RequireAdminOrApp", policy => policy.RequireRole("Admin,App").Build());
+                // 自定义权限要求
+                options.AddPolicy("Permission",
+                         policy => policy.Requirements.Add(permissionRequirement));
+            });
+            #endregion
+
+
+
+            //log日志注入
+            services.AddSingleton<ILoggerHelper, LogHelper>();
+
+
+            #region 缓存 读取配置是否使用哪种缓存模式
+            services.AddMemoryCache();
+            if (Convert.ToBoolean(Configuration["Cache:IsUseRedis"]))
+            {
+                services.AddSingleton<ICacheService, RedisCacheService>();
+            }
+            else
+            {
+                services.AddSingleton<ICacheService, MemoryCacheService>();
+            }
+            #endregion
+
+            #region 缓存 RedisCache
+            //将Redis分布式缓存服务添加到服务中
+            services.AddDistributedRedisCache(options =>
+            {
+                //用于连接Redis的配置 
+                options.Configuration = "localhost";// Configuration.GetConnectionString("RedisConnectionString");
+                //Redis实例名RedisDistributedCache
+                options.InstanceName = "RedisInstance";
+            });
+            #endregion
+
+            #region CORS
+            services.AddCors(c =>
+            {
+                c.AddPolicy("Any", policy =>
+                {
+                    policy.AllowAnyOrigin()
+                    .AllowAnyMethod()
+                    .AllowAnyHeader()
+                    .AllowCredentials();
+                });
+
+                c.AddPolicy("Limit", policy =>
+                {
+                    policy
+                    .WithOrigins("localhost:63969")
+                    .WithMethods("get", "post", "put", "delete")
+                    //.WithHeaders("Authorization");
+                    .AllowAnyHeader();
+                });
+            });
+            #endregion
+
+            #region 性能 压缩
+            services.AddResponseCompression();
+            #endregion
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@@ -48,9 +194,33 @@ namespace HaBookCms.Contest
                 // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                 app.UseHsts();
             }
-
+            #region 解决Ubuntu Nginx 代理不能获取IP问题
+            app.UseForwardedHeaders(new ForwardedHeadersOptions
+            {
+                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
+            });
+            #endregion
             app.UseHttpsRedirection();
-            app.UseStaticFiles();
+            app.UseStaticFiles(new StaticFileOptions
+            {
+                ServeUnknownFileTypes = true
+                //ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
+                //{
+                //  { ".apk","application/vnd.android.package-archive"},
+                //  { ".nupkg","application/zip"}
+                //})  //支持特殊文件下载处理
+            });
+            //自定义异常处理
+            app.UseMiddleware<ExceptionFilter>();
+            //认证
+            app.UseAuthentication();
+            //授权
+            app.UseMiddleware<JwtAuthorizationFilter>();
+
+            //性能压缩
+            app.UseResponseCompression();
+
+
             app.UseCookiePolicy();
 
             app.UseMvc(routes =>

+ 0 - 1
HaBookCms.Core/HaBookCms.Core.csproj

@@ -5,7 +5,6 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <Folder Include="Models\Contest\" />
     <Folder Include="Models\Website\" />
   </ItemGroup>
 

+ 25 - 0
HaBookCms.Core/Models/Contest/ContestUser.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace HaBookCms.Core.Models.Contest
+{
+    /// <summary>
+    /// 竞赛
+    /// </summary>
+    public class ContestUser
+    {
+        public string Guid { get; set; }
+        public string UserName { get; set; }
+        public string NickName { get; set; }
+        public string Sex { get; set; }
+        public string Phone { get; set; }
+        public string Email { get; set; }
+        public string TeamModelId { get; set; }
+        public string Header { get; set; }
+        public string City { get; set; }
+        public string CityCode { get; set; }
+        public long RegisterTime { get; set; }
+        public string CountryCode { get; set; }
+    }
+}

+ 42 - 0
HaBookCms.Core/Models/Contest/LoginInfo.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace HaBookCms.Core.Models.Contest
+{
+    public class LoginInfo
+    {
+        /// <summary>
+        /// 自动生成
+        /// </summary>
+        public string Guid { get; set; }
+        /// <summary>
+        /// 醍摩豆ID
+        /// </summary>
+        public string TeamModelId { get; set; }
+        /// <summary>
+        /// 登录时间
+        /// </summary>
+        public long LoginTime { get; set; }
+        /// <summary>
+        /// token
+        /// </summary>
+        public string JwtToken { get; set; }
+        /// <summary>
+        /// 超时(秒)数
+        /// </summary>
+        public long Timeout { get; set; }
+        /// <summary>
+        /// 到期时间
+        /// </summary>
+        public long  Expires { get; set; }
+        /// <summary>
+        /// 醍摩豆 验证ticket
+        /// </summary>
+        public string Ticket { get; set; }
+        /// <summary>
+        /// 登录端 以便支持多端登录
+        /// </summary>
+        public string AppTokenType { get; set; }
+    }
+}