我一直在尝试将Identity Server 4与SPA应用程序集成。我能够在API中授权应用程序,但在授权后,User.Claims
始终为empty
,尽管我已在范围中添加了声明。
我在API中使用Asp.net Identity与实体框架核心。
我的项目分布在不同的项目中。
Startup.cs
对于Project.Admin
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddAuthorization();
services.AddIdentity<User, IdentityRole<Guid>>()
.AddEntityFrameworkStores<MyContext>()
.AddDefaultTokenProviders();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44305";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
services.AddCors(options =>
{
options.AddPolicy("default", policy =>
{
policy.WithOrigins("http://localhost:8080")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
services.AddScoped<IContractService, ContractService>();
services.AddScoped<IClientService, ClientService>();
services.AddAutoMapper(mapperConfig => mapperConfig.AddProfiles(GetType().Assembly));
services.AddMvcCore()
.AddJsonFormatters();
}
Identity Server Setup
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(typeof(MyContext).GetTypeInfo().Assembly.GetName().Name));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(typeof(MyContext).GetTypeInfo().Assembly.GetName().Name));
}).AddAspNetIdentity<User>();
TestUser.cs
public class TestUsers
{
public static List<TestUser> Users = new List<TestUser>
{
new TestUser{SubjectId = Guid.NewGuid().ToString(), Username = "alice", Password = "alice",
Claims =
{
new Claim(JwtClaimTypes.Name, "Alice Smith"),
new Claim(JwtClaimTypes.Role,"Admin"),
new Claim(JwtClaimTypes.GivenName, "Alice"),
new Claim(JwtClaimTypes.FamilyName, "Smith"),
new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json)
}
}
};
}
Client
new Client
{
ClientId = "js",
ClientName = "JavaScript Client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
AlwaysIncludeUserClaimsInIdToken = true,
RedirectUris = new List<string> {"http://localhost:8080/silent","http://localhost:8080/authredirect"},
PostLogoutRedirectUris = { "http://localhost:8080" },
AllowedCorsOrigins = { "http://localhost:8080" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1",
"role"
}
}
ApiResource
new ApiResource("api1", "My API")
IdentityResources
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"}
}
};
}
Decode Token
{
"nbf": 1525602392,
"exp": 1525605992,
"iss": "https://localhost:44305",
"aud": [
"https://localhost:44305/resources",
"api1"
],
"client_id": "js",
"sub": "c81ce899-77d9-4c34-ab31-b456129ee762",
"auth_time": 1525601959,
"idp": "local",
"scope": [
"openid",
"profile",
"role",
"api1"
],
"amr": [
"pwd"
]
}
为什么API能够授权和验证请求,但没有关于用户和声明的详细信息?我错过了API启动课上的任何内容吗?或者在启动类的优先级上存在一些错误配置。
在我为启动类添加了上下文和服务的DI之前,声明和用户曾经拥有该值。
我再次尝试删除对Project.Service的引用,并从Project.Admin中的Statrup类中删除所有内容。我能够获得索赔信息。如下图所示。
然而,当我将DI添加到Context和其他服务时。我的索赔信息丢失了。但是,我仍然通过身份验证,并通过了我的授权过滤器。
编辑:当我检查我的应用程序上的日志时发现错误
&#34; Identity.Application&#34;未经过身份验证。失败消息:&#34;取消保护票证失败&#34;
答案 0 :(得分:0)
试试这个
$getID3 = new getID3;
$OldThisFileInfo = $getID3->analyze($Path);
if(isset($OldThisFileInfo['comments']['picture'][0]))
{
header('Content-Type: ' . $OldThisFileInfo['comments']['picture'][0]['image_mime']);
echo $OldThisFileInfo['comments']['picture'][0]['data'];
die;
}
我不是专家,但我认为这是你应该如何处理声明,而不是旧版本的Asp.Net,其中放置用户足够
答案 1 :(得分:0)
我找到了解决这个问题的方法。我在代码上遗漏了几件事:
IdentityServer4.AccessTokenValidation
的重复引用。我错过了我的API DefaultChallengeScheme
ConfigureServices
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44305";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
所以我的配置服务变得如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore().AddAuthorization().AddJsonFormatters();
var connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<MyContext>(o => o.UseSqlServer(connectionString));
services.AddIdentity<User, IdentityRole<Guid>>().AddEntityFrameworkStores<MyContext>().AddDefaultTokenProviders();
services.AddAuthentication(
options =>
{
options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44305";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
services.AddCors(options =>
{
// this defines a CORS policy called "default"
options.AddPolicy("default", policy =>
{
policy.WithOrigins("http://localhost:8080")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
services.AddScoped<IContractService, ContractService>();
services.AddScoped<IClientService, ClientService>();
services.AddAutoMapper(mapperConfig => mapperConfig.AddProfiles(GetType().Assembly));
}
更改以上两项内容解决了我的遗漏索赔问题以及没有承载令牌的Authorized
。