簡體   English   中英

授權屬性不起作用身份服務器 4

[英]Authorize attribute not working identity server 4

問題

我有一個三個項目。

  1. web 應用
  2. API
  3. 身份服務器

這是一個快速更新。

我可以使用下面的代碼訪問 api 安全性,但是它只能作為用戶傳遞客戶端。

        try
        {
          
            var client = new HttpClient();
            var disco = await client.GetDiscoveryDocumentAsync("https://localhost:44302/");
            if (disco.IsError)
            {
                Console.WriteLine(disco.Error);
            }

            var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = disco.TokenEndpoint,

                ClientId = "client",
                ClientSecret = "secret",
                Scope = "crmApi"
            });

            if (tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
            }

            Console.WriteLine(tokenResponse.Json);
            //get currently logged on user
            //set network credentials/
            var httpHandler = new HttpClientHandler();
            httpHandler.UseDefaultCredentials = true;
            using (HttpClient c = new HttpClient(httpHandler))
            {
                
                c.SetBearerToken(tokenResponse.AccessToken);
                string page = "https://localhost:44314/weatherforecast";
                using (HttpResponseMessage response = await c.GetAsync(page))
                using (HttpContent content = response.Content)
                {
                    // ... Read the string.
                    string result = await content.ReadAsStringAsync();

                    // ... Display the result.
                    if (result != null &&
                        result.Length >= 50)
                    {
                        Console.WriteLine(result.Substring(0, 50) + "...");
                    }
                }
            }
           
            return View();
        }
        catch (Exception)
        {

            throw;
        }
   

這是我看到的,然后我在身份服務器上對客戶端進行身份驗證。

True; AuthenticationTypes.Federation;
s_hash  8Q2BLwDYoIZ-4IwN4d26MA
sid     1FD1B63201F0B500A4433810F79C1A12
sub     645fd73d-d3b8-48b3-b398-8edd3c9e5b81
auth_time   1596209970
idp     local
preferred_username  admin
name    admin
amr     pwd

這是我給 api 的電話

            string page = "https://localhost:44314/weatherforecast";
         
            HttpClientHandler httpClientHandler = new HttpClientHandler();
            httpClientHandler.UseDefaultCredentials = true;

            using (HttpClient client = new HttpClient(httpClientHandler))
            {
               
                using (HttpResponseMessage response = await client.GetAsync(page))
                using (HttpContent content = response.Content)
                {
                    // ... Read the string.
                    string result = await content.ReadAsStringAsync();

                    // ... Display the result.
                    if (result != null &&
                        result.Length >= 50)
                    {
                        Console.WriteLine(result.Substring(0, 50) + "...");
                    }
                }
            }

我遇到的問題是,當我將授權屬性添加到 api 控制器時,我無法訪問 API。 日志中唯一說的是承載身份驗證受到質疑。

這是我來自身份服務器的配置文件

public class Config
{
    

    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
             new IdentityResources.Email(),
            new IdentityResource
            {
                Name = "role",
                UserClaims = new List<string> {"role"}
            }
        };
    }

    public static IEnumerable<ApiResource> GetAllApiResources()
    {
        return new List<ApiResource>
        {
           new ApiResource
            {
                Name = "crmApi",
                DisplayName = "API #1",
                Description = "Allow the application to access API #1 on your behalf",
                Scopes = new List<string> {"crmApi"},
                ApiSecrets = new List<Secret> {new Secret("secret".Sha256())}, // change me!
                UserClaims = new List<string> {"role"}
                
            }
        };
    }

    public static IEnumerable<ApiScope> GetApiScopes()
    {
        return new[]
        {
            new ApiScope("crmApi", "Access to API #1"),
        };
    }

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "client",
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedScopes = { "crmApi" }
            },

              new Client
        {
            ClientId = "mvc",
            ClientName = "MVC Client",
            AllowedGrantTypes = GrantTypes.Implicit,
          RedirectUris = {"https://localhost:44315/signin-oidc"},
          PostLogoutRedirectUris = {"https://localhost:44315/signout-callback-oidc"},

           AllowedScopes =new List<string>
           {
               IdentityServerConstants.StandardScopes.OpenId,
               IdentityServerConstants.StandardScopes.Profile,
               IdentityServerConstants.StandardScopes.Email,
              "role",
              "crmApi"
           }
        },
    };


    }
}

這是身份服務器啟動文件

   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.AddMvc(option => option.EnableEndpointRouting = false);

        var connectionString = Configuration.GetSection("ConnectionStrings:Database").Value;
        var migrationAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

        services.AddDbContext<ApplicationDbContext>(builder =>
         builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationAssembly)));
        services.AddIdentity<IdentityUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationAssembly));
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationAssembly));
            })
            .AddAspNetIdentity<IdentityUser>();

        services.AddCors();
        services.AddLogging();
        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        InitialISDatabase(app);

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();
        app.UseIdentityServer();
        app.UseAuthorization();
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });
        app.UseCors();
        app.UseMvcWithDefaultRoute();
    }

    private void InitialISDatabase(IApplicationBuilder app)
    {
        using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
        {
            serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
            serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>().Database.Migrate();
            serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();

            var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
            var u = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

            if (!context.Clients.Any())
            {
                foreach (var client in Config.GetClients())
                {
                    context.Clients.Add(client.ToEntity());
                }

                context.SaveChanges();
            }


            if (!context.IdentityResources.Any())
            {
                foreach (var resource in Config.GetIdentityResources())
                {
                    context.IdentityResources.Add(resource.ToEntity());
                }

                context.SaveChanges();
            }

            if (!context.ApiScopes.Any())
            {
                foreach (var scope in Config.GetApiScopes())
                {
                    context.ApiScopes.Add(scope.ToEntity());
                }
                context.SaveChanges();
            }

            if (!context.ApiResources.Any())
            {
                foreach (var api in Config.GetAllApiResources())
                {
                    context.ApiResources.Add(api.ToEntity());
                }

                context.SaveChanges();
            }


            if (!u.Users.Any())
            {

                var identityUser = new IdentityUser();
                identityUser.UserName = "admin";
                PasswordHasher<IdentityUser> hasher = new PasswordHasher<IdentityUser>();
                identityUser.PasswordHash = hasher.HashPassword(identityUser, "123qwe");
                identityUser.Email = "admin@crm.com";
                identityUser.NormalizedEmail = "admin@crm.com".ToUpper();
                identityUser.NormalizedUserName = "admin".ToUpper();
                identityUser.SecurityStamp = Guid.NewGuid().ToString();

                u.Users.Add(identityUser);

                u.SaveChanges();


            }

        }
    }

這是 api 啟動文件。

    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.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
            .AddIdentityServerAuthentication(options =>
            {
                options.Authority = "https://localhost:44302/";
                options.ApiName = "crmApi";
                options.RequireHttpsMetadata = false;
               
            });

        services.AddAuthorization();
        services.AddControllers();

      
    }

    // 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.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();
        app.UseHttpsRedirection();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

這里是web項目啟動文件。

   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.AddControllersWithViews();

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";
            options.Authority = "https://localhost:44302/";
            options.RequireHttpsMetadata = false;
            options.ClientId = "mvc";
            options.SaveTokens = true;
        });

    }

    // 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())
        {
           
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseDeveloperExceptionPage();

        app.UseHttpsRedirection();

        app.UseStaticFiles();

        app.UseRouting();


        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

在從客戶端接收訪問令牌的 API 中,您應該使用:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(opt =>
    {
        opt.Audience = "payment";  //api name
        opt.Authority = "https://identityservice.local:6001";  //URL to your identityserver
    });

AddIdentityServerAuthentication 不適用於 API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM