[英]Authorize attribute not working identity server 4
問題
我有一個三個項目。
這是一個快速更新。
我可以使用下面的代碼訪問 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.