public async Task <UnifyResponseDto> CreateAsync([FromBody] CreateUpdateBookDto createBook) { await _bookService.CreateAsync(createBook); return(UnifyResponseDto.Success("新建图书成功")); }
public void ConfigureServices(IServiceCollection services) { InMemoryConfiguration.Configuration = this.Configuration; services.AddContext(); services.AddIdentityServer() #if DEBUG .AddDeveloperSigningCredential() #endif #if !DEBUG .AddSigningCredential(new X509Certificate2( Path.Combine(AppContext.BaseDirectory, Configuration["Certificates:Path"]), Configuration["Certificates:Password"]) ) #endif .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region Swagger //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo() { Title = "LinCms.IdentityServer4", Version = "v1" }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath); }); #endregion services.AddTransient <IUserRepository, UserRepository>(); services.AddTransient <IUserIdentityService, UserIdentityService>(); services.AddTransient <ICurrentUser, CurrentUser>(); services.AddTransient(typeof(IAuditBaseRepository <>), typeof(AuditBaseRepository <>)); services.AddTransient(typeof(IAuditBaseRepository <,>), typeof(AuditBaseRepository <,>)); services.AddTransient <CustomExceptionMiddleWare>(); services.AddCors(); services.AddAutoMapper(typeof(UserProfile).Assembly); services.AddControllers(options => { //options.Filters.Add<LinCmsExceptionFilter>(); }) .AddNewtonsoftJson(opt => { //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true } }; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); services.AddHealthChecks(); }
public async Task <UnifyResponseDto> CreateAsync([FromBody] CreateUpdateBaseTypeDto createBaseType) { await _baseTypeService.CreateAsync(createBaseType); return(UnifyResponseDto.Success("新建类别成功")); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddContext(); #region IdentityServer4 #region AddAuthentication\AddIdentityServerAuthentication //AddAuthentication()是把验证服务注册到DI, 并配置了Bearer作为默认模式. //AddIdentityServerAuthentication()是在DI注册了token验证的处理者. //由于是本地运行, 所以就不使用https了, RequireHttpsMetadata = false.如果是生产环境, 一定要使用https. //Authority指定Authorization Server的地址. //ApiName要和Authorization Server里面配置ApiResource的name一样. //和 AddJwtBearer不能同时使用,目前还不理解区别。 //services // .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) // .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => // { // options.RequireHttpsMetadata = false; // for dev env // options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; ; // options.ApiName = Configuration["Service:Name"]; // match with configuration in IdentityServer // //options.JwtValidationClockSkew = TimeSpan.FromSeconds(60 * 5); // }); #endregion #region AddJwtBearer services.AddAuthentication(opts => { opts.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = "/cms/oauth2/signin"; options.LogoutPath = "/cms/oauth2/signout"; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { //identityserver4 地址 也就是本项目地址 options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; options.RequireHttpsMetadata = false; options.Audience = Configuration["Service:Name"]; options.TokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey( Encoding.ASCII.GetBytes(Configuration["Authentication:JwtBearer:SecurityKey"])), // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = Configuration["Authentication:JwtBearer:Issuer"], // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = Configuration["Authentication:JwtBearer:Audience"], // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here //ClockSkew = TimeSpan.Zero }; //options.TokenValidationParameters = new TokenValidationParameters() //{ // ClockSkew = TimeSpan.Zero //偏移设置为了0s,用于测试过期策略,完全按照access_token的过期时间策略,默认原本为5分钟 //}; //使用Authorize设置为需要登录时,返回json格式数据。 options.Events = new JwtBearerEvents() { OnAuthenticationFailed = context => { //Token expired if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Add("Token-Expired", "true"); } return(Task.CompletedTask); }, OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦 context.HandleResponse(); string message; ErrorCode errorCode; int statusCode = StatusCodes.Status401Unauthorized; if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired") { message = "令牌过期"; errorCode = ErrorCode.TokenExpired; statusCode = StatusCodes.Status422UnprocessableEntity; } else if (context.Error == "invalid_token" && context.ErrorDescription.IsNullOrEmpty()) { message = "令牌失效"; errorCode = ErrorCode.TokenInvalidation; } else { message = "请先登录"; //""认证失败,请检查请求头或者重新登录"; errorCode = ErrorCode.AuthenticationFailed; } context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; context.Response.WriteAsync(new UnifyResponseDto(errorCode, message, context.HttpContext).ToString()); return(Task.FromResult(0)); } }; }) .AddGitHub(options => { options.ClientId = Configuration["Authentication:GitHub:ClientId"]; options.ClientSecret = Configuration["Authentication:GitHub:ClientSecret"]; options.Scope.Add("user:email"); //authenticateResult.Principal.FindFirst(ClaimTypes.Uri)?.Value; 得到GitHub头像 options.ClaimActions.MapJsonKey(LinConsts.Claims.AvatarUrl, "avatar_url"); options.ClaimActions.MapJsonKey(LinConsts.Claims.BIO, "bio"); options.ClaimActions.MapJsonKey(LinConsts.Claims.BlogAddress, "blog"); }); #endregion #endregion services.AddCsRedisCore(); services.AddAutoMapper(typeof(UserProfile).Assembly, typeof(PoemProfile).Assembly); services.AddCors(); #region Mvc services.AddControllers(options => { options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //设置SnakeCase形式的QueryString参数 //options.Filters.Add<LinCmsExceptionFilter>(); options.Filters.Add <LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 }) .AddNewtonsoftJson(opt => { //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true } }; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); #endregion services.AddServices(); string serviceName = Configuration.GetSection("FILE:SERVICE").Value; if (serviceName == LinFile.LocalFileService) { services.AddTransient <IFileService, LocalFileService>(); } else { services.AddTransient <IFileService, QiniuService>(); } #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor .Transient <IApiDescriptionProvider, SnakeCaseQueryParametersApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo() { Title = "LinCms", Version = "v1" }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath); }); #endregion services.Configure <FormOptions>(options => { options.MultipartBodyLengthLimit = 1024 * 1024 * 2; options.MultipartHeadersCountLimit = 10; }); IConfigurationSection configurationSection = Configuration.GetSection("ConnectionStrings:MySql"); services.AddCap(x => { x.UseMySql(configurationSection.Value); x.UseRabbitMQ(options => { options.HostName = Configuration["RabbitMQ:HostName"]; options.UserName = Configuration["RabbitMQ:UserName"]; options.Password = Configuration["RabbitMQ:Password"]; options.VirtualHost = Configuration["RabbitMQ:VirtualHost"]; }); x.UseDashboard(); x.FailedRetryCount = 5; x.FailedThresholdCallback = (type, message) => { Console.WriteLine( $@"A message of type {type} failed after executing {x.FailedRetryCount} several times, requiring manual troubleshooting. Message name: {message.GetName()}"); }; }); services.AddStartupTask <MigrationStartupTask>(); services.AddHealthChecks(); }
public UnifyResponseDto CreateAsync([FromBody] ResourceDto createResource) { _resourceService.CreateAsync(createResource); return(UnifyResponseDto.Success("新建成功")); }
public async Task <UnifyResponseDto> UpdateAsync(long id, [FromBody] CreateUpdateDocDto updateDoc) { await _docService.UpdateAsync(id, updateDoc); return(UnifyResponseDto.Success("编辑文档成功")); }
public async Task <UnifyResponseDto> UpdateAsync(Guid id, [FromBody] CreateUpdateTagDto updateTag) { await _tagService.UpdateAsync(id, updateTag); return(UnifyResponseDto.Success("更新标签成功")); }
public void ConfigureServices(IServiceCollection services) { //services.AddFreeSql(Configuration); services.AddCsRedisCore(Configuration); services.AddJwtBearer(Configuration); services.AddAutoMapper(typeof(UserProfile).Assembly, typeof(PoemProfile).Assembly); services.AddCors(); #region Mvc services.AddMvc(options => { options.ValueProviderFactories.Add(new ValueProviderFactory()); //设置SnakeCase形式的QueryString参数 //options.Filters.Add<LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 options.Filters.Add <LinCmsExceptionFilter>(); // }) .AddNewtonsoftJson(opt => { opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; // 设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { //ProcessDictionaryKeys = true }, }; }) .ConfigureApiBehaviorOptions(options => { //options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); #endregion //配置Google验证码 services.AddScoped <RecaptchaVerifyActionFilter>(); services.Configure <GooglereCAPTCHAOptions>(Configuration.GetSection(GooglereCAPTCHAOptions.RecaptchaSettings)); GooglereCAPTCHAOptions googlereCAPTCHAOptions = services.BuildServiceProvider().GetService <IOptionsSnapshot <GooglereCAPTCHAOptions> >().Value; if (googlereCAPTCHAOptions.Enabled) { services.AddreCAPTCHAV3(x => { x.VerifyBaseUrl = googlereCAPTCHAOptions.VerifyBaseUrl; x.SiteKey = googlereCAPTCHAOptions.SiteKey; x.SiteSecret = googlereCAPTCHAOptions.SiteSecret; }); } services.AddDIServices(Configuration); services.AddSwaggerGenNewtonsoftSupport(); //Swagger 扩展方法配置Swagger services.AddSwaggerGen(); //应用程序级别设置 services.Configure <FormOptions>(options => { //单个文件上传的大小限制为8 MB 默认134217728 应该是128MB options.MultipartBodyLengthLimit = 1024 * 1024 * 8; //8MB }); // 分布式事务一致性CAP services.AddCap(Configuration); services.Configure <ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); //之前请注入AddCsRedisCore,内部实现IDistributedCache接口 services.AddIpRateLimiting(Configuration); services.AddHealthChecks(); }
public async Task <UnifyResponseDto> DeleteMyComment(Guid id) { await _commentService.DeleteMyComment(id); return(UnifyResponseDto.Success()); }
public void ConfigureServices(IServiceCollection services) { services.AddContext(Configuration); services.AddCsRedisCore(Configuration); JsonWebTokenSettings jsonWebTokenSettings = services.AddSecurity(Configuration); #region AddJwtBearer services.AddAuthentication(opts => { opts.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddCookie() .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { bool isIds4 = Configuration["Service:IdentityServer4"].ToBoolean(); if (isIds4) { //identityserver4 地址 也就是本项目地址 options.Authority = Configuration["Service:Authority"]; } options.RequireHttpsMetadata = Configuration["Service:UseHttps"].ToBoolean(); options.Audience = Configuration["Service:Name"]; options.TokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = jsonWebTokenSettings.SecurityKey, // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = jsonWebTokenSettings.Issuer, // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = jsonWebTokenSettings.Audience, // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set thatValidIssuer here //ClockSkew = TimeSpan.Zero }; //options.TokenValidationParameters = new TokenValidationParameters() //{ // ClockSkew = TimeSpan.Zero //偏移设置为了0s,用于测试过期策略,完全按照access_token的过期时间策略,默认原本为5分钟 //}; //使用Authorize设置为需要登录时,返回json格式数据。 options.Events = new JwtBearerEvents() { OnAuthenticationFailed = context => { //Token expired if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Add("Token-Expired", "true"); } return(Task.CompletedTask); }, OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦 context.HandleResponse(); string message; ErrorCode errorCode; int statusCode = StatusCodes.Status401Unauthorized; if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired") { message = "令牌过期"; errorCode = ErrorCode.TokenExpired; statusCode = StatusCodes.Status422UnprocessableEntity; } else if (context.Error == "invalid_token" && context.ErrorDescription.IsNullOrEmpty()) { message = "令牌失效"; errorCode = ErrorCode.TokenInvalidation; } else { message = "请先登录" + context.ErrorDescription; //""认证失败,请检查请求头或者重新登录"; errorCode = ErrorCode.AuthenticationFailed; } context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; context.Response.WriteAsync(new UnifyResponseDto(errorCode, message, context.HttpContext).ToString()); return(Task.FromResult(0)); } }; }) .AddGitHub(options => { options.ClientId = Configuration["Authentication:GitHub:ClientId"]; options.ClientSecret = Configuration["Authentication:GitHub:ClientSecret"]; options.Scope.Add("user:email"); options.ClaimActions.MapJsonKey(LinConsts.Claims.AvatarUrl, "avatar_url"); options.ClaimActions.MapJsonKey(LinConsts.Claims.HtmlUrl, "html_url"); //登录成功后可通过 authenticateResult.Principal.FindFirst(ClaimTypes.Uri)?.Value; 得到GitHub头像 options.ClaimActions.MapJsonKey(LinConsts.Claims.BIO, "bio"); options.ClaimActions.MapJsonKey(LinConsts.Claims.BlogAddress, "blog"); }) .AddQQ(options => { options.ClientId = Configuration["Authentication:QQ:ClientId"]; options.ClientSecret = Configuration["Authentication:QQ:ClientSecret"]; }) .AddGitee(GiteeAuthenticationDefaults.AuthenticationScheme, "码云", options => { options.ClientId = Configuration["Authentication:Gitee:ClientId"]; options.ClientSecret = Configuration["Authentication:Gitee:ClientSecret"]; options.ClaimActions.MapJsonKey("urn:gitee:avatar_url", "avatar_url"); options.ClaimActions.MapJsonKey("urn:gitee:blog", "blog"); options.ClaimActions.MapJsonKey("urn:gitee:bio", "bio"); options.ClaimActions.MapJsonKey("urn:gitee:html_url", "html_url"); //options.Scope.Add("projects"); //options.Scope.Add("pull_requests"); //options.Scope.Add("issues"); //options.Scope.Add("notes"); //options.Scope.Add("keys"); //options.Scope.Add("hook"); //options.Scope.Add("groups"); //options.Scope.Add("gists"); //options.Scope.Add("enterprises"); options.SaveTokens = true; }); #endregion services.AddAutoMapper(typeof(UserProfile).Assembly, typeof(PoemProfile).Assembly); services.AddCors(); #region Mvc services.AddControllers(options => { options.ValueProviderFactories.Add(new ValueProviderFactory()); //设置SnakeCase形式的QueryString参数 //options.Filters.Add<LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 options.Filters.Add <LinCmsExceptionFilter>(); // }) .AddNewtonsoftJson(opt => { opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; // 设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { //ProcessDictionaryKeys = true }, }; }) .ConfigureApiBehaviorOptions(options => { //options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); services.AddSwaggerGenNewtonsoftSupport(); #endregion services.AddDIServices(Configuration); #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor.Transient <IApiDescriptionProvider, ApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { string ApiName = "LinCms.Web"; options.SwaggerDoc("v1", new OpenApiInfo() { Title = ApiName + RuntimeInformation.FrameworkDescription, Version = "v1", Contact = new OpenApiContact { Name = ApiName, Email = "*****@*****.**", Url = new Uri("https://www.cnblogs.com/igeekfan/") }, License = new OpenApiLicense { Name = ApiName + " 官方文档", Url = new Uri("https://luoyunchong.github.io/vovo-docs/dotnetcore/lin-cms/dotnetcore-start.html") } }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = JwtBearerDefaults.AuthenticationScheme, Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security); //添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); try { string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath, true); //实体层的xml文件名 string xmlEntityPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(IEntity).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlEntityPath); //Dto所在类库 string applicationPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(IApplicationService).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(applicationPath); } catch (Exception ex) { Log.Logger.Warning(ex.Message); } }); #endregion //应用程序级别设置 services.Configure <FormOptions>(options => { //单个文件上传的大小限制为8 MB 默认134217728 应该是128MB options.MultipartBodyLengthLimit = 1024 * 1024 * 8; //8MB }); // 分布式事务一致性CAP services.AddCap(Configuration); services.Configure <ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; }); //之前请注入AddCsRedisCore,内部实现IDistributedCache接口 services.AddIpRateLimiting(Configuration); services.AddHealthChecks(); }
public UnifyResponseDto Info() { return(UnifyResponseDto.Success("Lin 是一套基于 Python-Flask 的一整套开箱即用的后台管理系统(CMS)。Lin 遵循简洁、高效的原则,通过核心库加插件的方式来驱动整个系统高效的运行")); }
public async Task <IActionResult> SignInBindCallBack(string provider, string redirectUrl = "", string token = "") { if (string.IsNullOrWhiteSpace(provider)) { return(BadRequest()); } if (!await HttpContext.IsProviderSupportedAsync(provider)) { return(BadRequest()); } if (token.IsNullOrEmpty() || !token.StartsWith("Bearer ")) { return(Redirect($"{redirectUrl}#bind-result?code={ErrorCode.Fail}&message={HttpUtility.UrlEncode("请先登录")}")); } else { token = token.Remove(0, 7); } AuthenticateResult authenticateResult = await _contextAccessor.HttpContext.AuthenticateAsync(provider); if (!authenticateResult.Succeeded) { return(Redirect($"{redirectUrl}#bind-result?code=fail&message={authenticateResult.Failure.Message}")); } var openIdClaim = authenticateResult.Principal.FindFirst(ClaimTypes.NameIdentifier); if (openIdClaim == null || string.IsNullOrWhiteSpace(openIdClaim.Value)) { return(Redirect($"{redirectUrl}#bind-result?code={ErrorCode.Fail}&message={HttpUtility.UrlEncode("未能获取openId")}")); } JwtPayload jwtPayload = (JwtPayload)_jsonWebTokenService.Decode(token); string nameIdentifier = jwtPayload.Claims.FirstOrDefault(r => r.Type == ClaimTypes.NameIdentifier)?.Value; if (nameIdentifier.IsNullOrWhiteSpace()) { return(Redirect($"{redirectUrl}#bind-result?code={ErrorCode.Fail}&message={HttpUtility.UrlEncode("请先登录")}")); } long userId = long.Parse(nameIdentifier); UnifyResponseDto unifyResponseDto; List <string> supportProviders = new List <string> { LinUserIdentity.Gitee, LinUserIdentity.GitHub, LinUserIdentity.QQ }; if (!supportProviders.Contains(provider)) { _logger.LogError($"未知的privoder:{provider},redirectUrl:{redirectUrl}"); unifyResponseDto = UnifyResponseDto.Error($"未知的privoder:{provider}!"); } else { IOAuth2Service oAuth2Service = _componentContext.ResolveNamed <IOAuth2Service>(provider); unifyResponseDto = await oAuth2Service.BindAsync(authenticateResult.Principal, provider, openIdClaim.Value, userId); } return(Redirect($"{redirectUrl}#bind-result?code={unifyResponseDto.Code.ToString()}&message={HttpUtility.UrlEncode(unifyResponseDto.Message.ToString())}")); }
public UnifyResponseDto Logout() { return(UnifyResponseDto.Success("退出登录")); }
public async Task <UnifyResponseDto> PutAsync(int id, [FromBody] CreateUpdateBookDto updateBook) { await _bookService.UpdateAsync(id, updateBook); return(UnifyResponseDto.Success("更新图书成功")); }
public void ConfigureServices(IServiceCollection services) { InMemoryConfiguration.Configuration = this.Configuration; services.AddContext(); services.AddCors(); services.ConfigureApplicationCookie(options => { options.LoginPath = "/account/login"; }); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(120); }); services.AddIdentityServer(options => new IdentityServerOptions { UserInteraction = new UserInteractionOptions { LoginUrl = "/account/login", LogoutUrl = "/account/logout", } }) #if DEBUG .AddDeveloperSigningCredential() #endif #if !DEBUG .AddSigningCredential(new X509Certificate2( Path.Combine(AppContext.BaseDirectory, Configuration["Certificates:Path"]), Configuration["Certificates:Password"]) ) #endif .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiScopes(InMemoryConfiguration.GetApiScopes()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region Swagger //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { string ApiName = "LinCms.IdentityServer4"; options.SwaggerDoc("v1", new OpenApiInfo() { Title = ApiName + RuntimeInformation.FrameworkDescription, Version = "v1", Contact = new OpenApiContact { Name = ApiName, Email = "*****@*****.**", Url = new Uri("https://www.cnblogs.com/igeekfan/") }, License = new OpenApiLicense { Name = ApiName + " 官方文档", Url = new Uri("https://luoyunchong.github.io/vovo-docs/dotnetcore/lin-cms/dotnetcore-start.html") } }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); try { string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath, true); } catch (Exception ex) { Log.Logger.Warning(ex.Message); } options.AddServer(new OpenApiServer() { Url = "", Description = "vvv" }); options.CustomOperationIds(apiDesc => { var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor; return(controllerAction.ControllerName + "-" + controllerAction.ActionName); }); }); #endregion services.AddTransient <IUserRepository, UserRepository>(); services.AddTransient <IUserIdentityService, UserIdentityService>(); services.AddTransient <ICurrentUser, CurrentUser>(); services.AddTransient(typeof(IAuditBaseRepository <>), typeof(AuditBaseRepository <>)); services.AddTransient(typeof(IAuditBaseRepository <,>), typeof(AuditBaseRepository <,>)); //services.AddTransient<CustomExceptionMiddleWare>(); services.AddAutoMapper(typeof(UserProfile).Assembly); services.AddControllersWithViews(options => { options.Filters.Add <LinCmsExceptionFilter>(); }) .AddNewtonsoftJson(opt => { //忽略循环引用 opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 //opt.SerializerSettings.ContractResolver = new DefaultContractResolver() //{ // NamingStrategy = new SnakeCaseNamingStrategy() // { // ProcessDictionaryKeys = true // } //}; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); services.AddHealthChecks(); }
public async Task <UnifyResponseDto> CreateAsync([FromBody] CreateCommentDto createCommentDto) { await _commentService.CreateAsync(createCommentDto); return(UnifyResponseDto.Success("评论成功")); }
public async Task <UnifyResponseDto> CreateAsync([FromBody] CreateUpdateDocDto createDoc) { await _docService.CreateAsync(createDoc); return(UnifyResponseDto.Success("新增文档成功")); }
public override void OnActionExecuted(ActionExecutedContext context) { Stopwatch.Stop(); //当方法或控制器上存在DisableAuditingAttribute特性标签时,不记录日志 if (context.ActionDescriptor is ControllerActionDescriptor d && d.MethodInfo.IsDefined(typeof(DisableAuditingAttribute), true) || context.Controller.GetType().IsDefined(typeof(DisableAuditingAttribute), true) ) { base.OnActionExecuted(context); return; } LinLog linLog = new LinLog() { Method = context.HttpContext.Request.Method, Path = context.HttpContext.Request.Path, StatusCode = context.HttpContext.Response.StatusCode, OtherMessage = $"参数:{ActionArguments}\n耗时:{Stopwatch.Elapsed.TotalMilliseconds} 毫秒" }; ControllerActionDescriptor auditActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; AuditingLogAttribute auditingLogAttribute = auditActionDescriptor.GetCustomAttribute <AuditingLogAttribute>(); if (auditingLogAttribute != null) { linLog.Message = auditingLogAttribute.Template; } LinCmsAuthorizeAttribute linCmsAttribute = auditActionDescriptor.GetCustomAttribute <LinCmsAuthorizeAttribute>(); if (linCmsAttribute != null) { linLog.Authority = linCmsAttribute.Permission; } base.OnActionExecuted(context); if (context.Result is ObjectResult objectResult && objectResult.Value != null) { if (objectResult.Value.ToString().Contains("ErrorCode")) { UnifyResponseDto resultDto = JsonConvert.DeserializeObject <UnifyResponseDto>(objectResult.Value.ToString()); resultDto.Request = LinCmsUtils.GetRequest(context.HttpContext); context.Result = new JsonResult(resultDto); if (linLog.Message.IsNullOrEmpty()) { linLog.Message = resultDto.Message?.ToString(); } } } linLog.Message += $"{_currentUser.UserName}访问{context.HttpContext.Request.Path},耗时:{Stopwatch.Elapsed.TotalMilliseconds} 毫秒"; _logRepository.Create(linLog); //记录文本日志 _logger.LogInformation(JsonConvert.SerializeObject(linLog)); }
public async Task <UnifyResponseDto> CreateAsync([FromBody] CreateUpdateTagDto createTag) { await _tagService.CreateAsync(createTag); return(UnifyResponseDto.Success("新建标签成功")); }
public async Task <UnifyResponseDto> Delete(Guid id) { await _articleService.DeleteAsync(id); return(UnifyResponseDto.Success()); }
public async Task <UnifyResponseDto> CorrectedTagCountAsync(Guid tagId) { await _tagService.CorrectedTagCountAsync(tagId); return(UnifyResponseDto.Success()); }
public async Task <UnifyResponseDto> RemovePermissions(RemovePermissionDto permissionDto) { await _permissionService.DeletePermissionsAsync(permissionDto); return(UnifyResponseDto.Success("删除权限成功")); }
public async Task <UnifyResponseDto> DeleteAsync(long id) { await _resourceService.DeleteAsync(id); return(UnifyResponseDto.Success()); }
public async Task <UnifyResponseDto> CreateAsync([FromBody] CreateGroupDto inputDto) { await _groupService.CreateAsync(inputDto); return(UnifyResponseDto.Success("新建分组成功")); }
public async Task <UnifyResponseDto> UpdateAsync([FromBody] ResourceDto updateResource) { await _resourceService.UpdateAsync(updateResource); return(UnifyResponseDto.Success("更新成功")); }
public async Task <UnifyResponseDto> UpdateAsync(long id, [FromBody] UpdateGroupDto updateGroupDto) { await _groupService.UpdateAsync(id, updateGroupDto); return(UnifyResponseDto.Success("更新分组成功")); }
public async Task <UnifyResponseDto> DeleteAsync(int id) { await _baseTypeService.DeleteAsync(id); return(UnifyResponseDto.Success()); }
public async Task <UnifyResponseDto> DeleteAsync(long id) { await _groupService.DeleteAsync(id); return(UnifyResponseDto.Success("删除分组成功")); }
public async Task <UnifyResponseDto> UpdateAsync(int id, [FromBody] CreateUpdateBaseTypeDto updateBaseType) { await _baseTypeService.UpdateAsync(id, updateBaseType); return(UnifyResponseDto.Success("更新类别成功")); }
public async Task <UnifyResponseDto> ResetPasswordAsync(long id, [FromBody] ResetPasswordDto resetPasswordDto) { await _userSevice.ResetPasswordAsync(id, resetPasswordDto); return(UnifyResponseDto.Success("密码修改成功")); }