.net Core仅通过WS-Fed进行身份验证

时间:2019-03-05 23:27:04

标签: c# authentication .net-core ws-federation identityserver2

我们正在向现有环境中添加一个新的.net核心Web应用程序,其中心是用于身份验证的Identity Server 2。创建新应用程序时,我很难让它使用现有的身份验证。

目标是使新应用程序中的每个页面都需要登录用户。新的应用程序具有一些用户表,但不需要默认的身份数据库(AspNetUsers等),也不需要其自己的登录对话框(也无需密码恢复等)。

为此,我将以下内容添加到ConfigureServices()中的Startup.cs文件中:

01:services.AddTransient<IUserStore<ApplicationUser>, E360UserStore<ApplicationUser>>();
02:services.AddTransient<IRoleStore<ApplicationRole<string>>, E360RoleStore<ApplicationRole<string>>>();
03:
04:var authenticationConfigSection = Configuration.GetSection("Authentication");
05:
06:services.AddAuthentication(/*"WsFederation"*/)
07:        .AddWsFederation(authenticationScheme: "WsFederation",
08:                         displayName: "Single Signin",
09:                         configureOptions: options =>
10:                         {
11:                             // MetadataAddress represents the Identity Server instance used to authenticate users.
12:                             options.MetadataAddress = authenticationConfigSection.GetValue<string>("MetadataAddress");
13:
14:                             // Wtrealm is the app's relying party identifier in the IS instance.
15:                             options.Wtrealm = authenticationConfigSection.GetValue<string>("Wtrealm");
16:
17:                             //options.SignInScheme = "WsFederation";
18:                         });
19:
20:services.AddMvc(config =>
21:                {
22:                    var policy = new AuthorizationPolicyBuilder(/*"WsFederation"*/)
23:                                 .RequireAuthenticatedUser()
24:                                 .Build();
25:
26:                    config.Filters.Add(new AuthorizeFilter(policy));
28:                })
29:        .AddJsonOptions(o => o.SerializerSettings.ContractResolver = new DefaultContractResolver())
30:        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

这将产生错误,“未指定authenticationScheme,并且未找到DefaultChallengeScheme。”因此,我尝试取消对三个“ WsFederation”字符串的注释,一次只注释一次。

我尝试先取消最后一个的注释:

22:var policy = new AuthorizationPolicyBuilder("WsFederation")
23:             .RequireAuthenticatedUser()
24:             .Build();

这将产生类似但不同的错误,“未指定authenticationScheme,并且未找到DefaultAuthenticateScheme。”

如果我改为取消注释其他两行(或两行):

06:services.AddAuthentication("WsFederation")    
17:options.SignInScheme = "WsFederation";

这将产生错误,“无法将远程身份验证处理程序的SignInScheme设置为其自身。如果未显式设置,则使用AuthenticationOptions.DefaultSignInScheme或DefaultScheme。”

如果我将应用程序配置为“普通”身份验证,如下所示:

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));

services.AddDefaultIdentity<ApplicationUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

然后我得到一个登录对话框,该对话框的右侧标有“ Single Signin”(单点登录)按钮,可以正常工作。 WsFederation登录名中的声明映射到在生成的身份数据库中手动创建的用户。

我在新模型中使用E360UserStore和E360RoleStore的意图是映射到FindByIdAsync()中的IdentityUser(我无法对此进行测试):

public class ApplicationUser : IdentityUser
{
    public User User { get; set; }

    public ApplicationUser(User user)
    {
        base.Id = User.IdentityGuid.ToString("D");
        base.Email = user.Person.EmailAddress;
        base.NormalizedEmail = user.Person.EmailAddress.ToLowerInvariant();
        base.UserName = user.Username;
        base.NormalizedUserName = user.Username.ToLowerInvariant();
        base.EmailConfirmed = true;
        User = user;
    }
}

我似乎找不到删除“默认”登录名并自动重定向到Identity Server登录名的秘诀。

感谢阅读!

更新:

@Rytmis建议我缺少的是定义cookie,这些cookie表示应用程序已“登录”,这是一个很好的观察,但是由于我不了解我的工作方式,我仍然缺少一个片段WS-Fed到cookie auth(以标识当前用户)。我更改了ConfigureServices代码,如下所示,这确实导致程序立即重定向到身份服务器,这是完美的选择,并且在登录后将其重定向回ws-fed端点,然后将其重定向回到初始页面。所有这些都是好消息,但是初始页面仍然看不到该用户已登录。 cookie已创建,但是我看不到登录方式如何,在哪里,或者是否从ws-fed转换为cookie?我定义了自定义的IUserStore和IRoleStore类,但这些类没有被使用或实例化。

services.AddAuthentication(sharedOptions =>
                           {
                               sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                               sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                               sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
                           })
        .AddWsFederation(authenticationScheme: "WsFederation",
                         displayName: "Single Signin",
                         configureOptions: options =>
                                           {
                                               // MetadataAddress represents the Identity Server instance used to authenticate users.
                                               options.MetadataAddress = authenticationConfigSection.GetValue<string>("MetadataAddress");

                                               // Wtrealm is the app's relying party identifier in the IS instance.
                                               options.Wtrealm = authenticationConfigSection.GetValue<string>("Wtrealm");

                                               //options.SignInScheme = "WsFederation";
                                           })
        .AddCookie(options =>
                   {
                       options.Cookie.SameSite = SameSiteMode.None;
                       options.Cookie.Name = "AuthCookie";
                       options.AccessDeniedPath = "/error/accessdenied";
                   });

services.AddScoped<UserManager<ApplicationUser>, UserManager<ApplicationUser>>();
services.AddTransient<IUserStore<ApplicationUser>, MyUserStore<ApplicationUser>>();
services.AddTransient<IRoleStore<ApplicationRole<string>>, MyRoleStore<ApplicationRole<string>>>();

1 个答案:

答案 0 :(得分:0)

具有远程身份验证的事情是,除非您希望对每个请求执行远程身份验证重定向,否则您将不得不在本地存储一些内容-没人这样做。

除了远程方案之外,您还需要指定一个本地身份验证方案,该方案将用于存储远程身份验证的结果。通常,这是通过添加Cookie身份验证处理程序并将其用作SignInScheme来完成的。