示例#1
0
 public SignInUserCommand(AppDbContext dbContext,
                          IJsonWebTokenService jsonWebTokenService,
                          JsonWebTokenSettings jsonWebTokenSettings)
 {
     _dbContext            = dbContext;
     _jsonWebTokenService  = jsonWebTokenService;
     _jsonWebTokenSettings = jsonWebTokenSettings;
 }
        public static JsonWebTokenSettings AddSecurity(this IServiceCollection services, IConfiguration configuration)
        {
            JsonWebTokenSettings jsonWebTokenSettings = new JsonWebTokenSettings(
                configuration["Authentication:JwtBearer:SecurityKey"],
                new TimeSpan(1, 0, 0, 0),
                configuration["Authentication:JwtBearer:Audience"],
                configuration["Authentication:JwtBearer:Issuer"]
                );

            services.AddHash(10000, 128);
            services.AddCryptography("lin-cms-dotnetcore-cryptography");
            services.AddJsonWebToken(jsonWebTokenSettings);
            return(jsonWebTokenSettings);
        }
示例#3
0
        private static JsonWebTokenSettings AddSecurity(this IServiceCollection services)
        {
            JsonWebTokenSettings jsonWebTokenSettings = new JsonWebTokenSettings(
                Appsettings.JwtBearer.SecurityKey,
                TimeSpan.FromMinutes(Appsettings.JwtBearer.Expires),
                Appsettings.JwtBearer.Audience,
                Appsettings.JwtBearer.Issuer
                );

            services.AddHashService();
            services.AddICryptographyService("Memoyu.Blog-cryptography");
            services.AddJsonWebTokenService(jsonWebTokenSettings);
            return(jsonWebTokenSettings);
        }
示例#4
0
        /// <summary>
        /// 根据配置文件创建JsonWebTokenSettings
        /// 默认过期时间为1天
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <returns>JsonWebTokenSettings</returns>
        public static JsonWebTokenSettings AddSecurity(this IServiceCollection services)
        {
            var jsonWebTokenSettings = new JsonWebTokenSettings(
                NpsEnvironment.NPS_AUTH_JWT_SECURITYKEY,
                new TimeSpan(NpsEnvironment.NPS_AUTH_JWT_EXPIRESIN.ToInt32OrDefault(15), 0, 0, 0),
                NpsEnvironment.NPS_AUTH_JWT_AUDIENCE,
                NpsEnvironment.NPS_AUTH_JWT_ISSUER
                );

            services.AddHash();
            services.AddCryptography(NpsEnvironment.NPS_AUTH_JWT_CRYPTOGRAPHY);
            services.AddJsonWebToken(jsonWebTokenSettings);
            return(jsonWebTokenSettings);
        }
示例#5
0
    public SecurityTests()
    {
        var services = new ServiceCollection();

        services.AddSingleton <ICryptographyService>(_ => new CryptographyService(Guid.NewGuid().ToString()));
        _cryptographyService = services.BuildServiceProvider().GetService <ICryptographyService>();

        services.AddSingleton <IHashService, HashService>();
        _hashService = services.BuildServiceProvider().GetService <IHashService>();

        var jsonWebTokenSettings = new JsonWebTokenSettings(Guid.NewGuid().ToString(), TimeSpan.FromHours(12));

        services.AddSingleton <IJsonWebTokenService>(_ => new JsonWebTokenService(jsonWebTokenSettings));
        _jsonWebTokenService = services.BuildServiceProvider().GetService <IJsonWebTokenService>();
    }
示例#6
0
        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);
                }

                options.AddServer(new OpenApiServer()
                {
                    Url         = "",
                    Description = "v1"
                });
                options.CustomOperationIds(apiDesc =>
                {
                    return(apiDesc.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null);
                });
            });

            #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 static void AddJsonWebToken(this IServiceCollection services, JsonWebTokenSettings jsonWebTokenSettings)
 {
     services.AddSingleton(_ => jsonWebTokenSettings);
     services.AddSingleton <IJsonWebToken, JsonWebToken>();
 }
        public static void AddJwtBearer(this IServiceCollection services, IConfiguration Configuration)
        {
            JsonWebTokenSettings jsonWebTokenSettings = services.AddSecurity(Configuration);

            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 = async 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;
                        await context.Response.WriteAsync(new UnifyResponseDto(errorCode, message, context.HttpContext).ToString());
                    }
                };
            })
            .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;
            });
        }
 public JsonWebTokenService(JsonWebTokenSettings jsonWebTokenSettings)
 {
     JsonWebTokenSettings = jsonWebTokenSettings;
 }
示例#10
0
        /// <summary>
        /// 注入JWT
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        public static void AddJwtBearer(this IServiceCollection services)
        {
            Log.Logger.Information("Initialize JwtBearer Start;");

            Check.NotNull(services, nameof(services));

            JsonWebTokenSettings jsonWebTokenSettings = services.AddSecurity();

            // 开启Bearer认证
            services.AddAuthentication(opts =>
            {
                opts.DefaultScheme             = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            // 添加JwtBearer服务
            .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
            {
                //令牌验证参数
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    //是否验证密钥
                    ValidateIssuerSigningKey = true,
                    //密钥
                    IssuerSigningKey = jsonWebTokenSettings.SecurityKey,

                    //是否验证发行人
                    ValidateIssuer = true,
                    ValidIssuer    = jsonWebTokenSettings.Issuer,

                    //是否验证受众人
                    ValidateAudience = true,
                    ValidAudience    = jsonWebTokenSettings.Audience,

                    //验证生命周期
                    ValidateLifetime = true,

                    //过期时间
                    RequireExpirationTime = true,

                    // 允许服务器时间偏移量300秒,即我们配置的过期时间加上这个允许偏移的时间值,才是真正过期的时间(过期时间 +偏移值)你也可以设置为0
                    //ClockSkew = TimeSpan.Zero
                };

                //使用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 = async context =>
                    {
                        //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦
                        context.HandleResponse();

                        string message;
                        StatusCode status;
                        int statusCode = StatusCodes.Status401Unauthorized;

                        if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired")
                        {
                            message    = "令牌过期";
                            status     = StatusCode.TokenExpired;
                            statusCode = StatusCodes.Status422UnprocessableEntity;
                        }
                        else if (context.Error == "invalid_token" && string.IsNullOrWhiteSpace(context.ErrorDescription))
                        {
                            message = "令牌失效";
                            status  = StatusCode.TokenInvalidation;
                        }
                        else
                        {
                            message = "请先登录 " + context.ErrorDescription; //""认证失败,请检查请求头或者重新登录";
                            status  = StatusCode.AuthenticationFailed;
                        }

                        context.Response.ContentType = "application/json";
                        context.Response.StatusCode  = statusCode;
                        await context.Response.WriteAsync(ExecuteResult.Error(message, status).ToJson());
                    }
                };
            });

            Log.Logger.Information("Initialize JwtBearer End;");
        }