コード例 #1
0
        /// <summary>
        /// 获取基于JWT的Token
        /// </summary>
        /// <param name="claims">需要在登陆的时候配置</param>
        /// <param name="permissionRequirement">在startup中定义的参数</param>
        /// <returns></returns>
        public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement)
        {
            var now = DateTime.Now;
            // 实例化JwtSecurityToken
            var jwt = new JwtSecurityToken(
                issuer: permissionRequirement.Issuer,
                audience: permissionRequirement.Audience,
                claims: claims,
                notBefore: now,
                expires: now.Add(permissionRequirement.Expiration),
                signingCredentials: permissionRequirement.SigningCredentials
                );
            // 生成 Token
            var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

            //打包返回前台
            var responseJson = new
            {
                success    = true,
                token      = encodedJwt,
                expires_in = permissionRequirement.Expiration.TotalSeconds,
                token_type = "Bearer"
            };

            return(responseJson);
        }
コード例 #2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            #region Swagger UI Service

            var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
            services.AddSwaggerGen(c =>
            {
                //遍历出全部的版本,做文档信息展示
                typeof(ApiVersions).GetEnumNames().ToList().ForEach(version =>
                {
                    c.SwaggerDoc(version, new Info
                    {
                        // {ApiName} 定义成全局变量,方便修改
                        Version        = version,
                        Title          = $"{ApiName} 接口文档",
                        Description    = $"{ApiName} HTTP API " + version,
                        TermsOfService = "None",
                        Contact        = new Contact {
                            Name = "Autho.JWT.Policy", Email = "*****@*****.**", Url = "https://www.jianshu.com/u/94102b59cc2a"
                        }
                    });
                    // 按相对路径排序,作者:Alby
                    c.OrderActionsBy(o => o.RelativePath);
                });


                //就是这里
                var xmlPath = Path.Combine(basePath, "Autho.JWT.Policy.xml"); //这个就是刚刚配置的xml文件名
                c.IncludeXmlComments(xmlPath, true);                          //默认的第二个参数是false,这个是controller的注释,记得修改


                #region Token绑定到ConfigureServices

                //添加header验证信息
                //c.OperationFilter<SwaggerHeader>();

                // 发行人
                var IssuerName = (Configuration.GetSection("Audience"))["Issuer"];
                var security   = new Dictionary <string, IEnumerable <string> > {
                    { IssuerName, new string[] { } },
                };
                c.AddSecurityRequirement(security);

                //方案名称“Autho.JWT.Policy”可自定义,上下一致即可
                c.AddSecurityDefinition(IssuerName, new ApiKeyScheme
                {
                    Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
                    Name        = "Authorization", //jwt默认的参数名称
                    In          = "header",        //jwt默认存放Authorization信息的位置(请求头中)
                    Type        = "apiKey"
                });
                #endregion
            });

            #endregion



            #region 【授权】

            #region 参数
            //读取配置文件
            var audienceConfig       = Configuration.GetSection("Audience");
            var symmetricKeyAsBase64 = audienceConfig["Secret"];
            var keyByteArray         = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey           = new SymmetricSecurityKey(keyByteArray);

            // 令牌验证参数
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey         = signingKey,
                ValidateIssuer           = true,
                ValidIssuer           = audienceConfig["Issuer"],   //发行人
                ValidateAudience      = true,
                ValidAudience         = audienceConfig["Audience"], //订阅人
                ValidateLifetime      = true,
                ClockSkew             = TimeSpan.Zero,
                RequireExpirationTime = true,
            };
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            // 如果要数据库动态绑定,这里先留个空,后边处理器里动态赋值
            var permission = new List <PermissionItem>();

            // 角色与接口的权限要求参数
            var permissionRequirement = new PermissionRequirement(
                "/api/denied",                           // 拒绝授权的跳转地址(目前无用)
                permission,
                ClaimTypes.Role,                         //基于角色的授权
                audienceConfig["Issuer"],                //发行人
                audienceConfig["Audience"],              //听众
                signingCredentials,                      //签名凭据
                expiration: TimeSpan.FromSeconds(60 * 2) //接口的过期时间
                );
            #endregion
            //【授权】
            services.AddAuthorization(options =>
            {
                options.AddPolicy("Permission",
                                  policy => policy.Requirements.Add(permissionRequirement));
            });
            #endregion


            #region 【认证】

            //2.1【认证】、官方JWT认证
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                o.TokenValidationParameters = tokenValidationParameters;
                o.Events = new JwtBearerEvents
                {
                    OnAuthenticationFailed = context =>
                    {
                        // 如果过期,则把<是否过期>添加到,返回头信息中
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            context.Response.Headers.Add("Token-Expired", "true");
                        }
                        return(Task.CompletedTask);
                    }
                };
            });

            // 注入权限处理器
            services.AddSingleton <IAuthorizationHandler, PermissionHandler>();
            services.AddSingleton(permissionRequirement);
            #endregion
        }