一个MVC Web应用程序作为API和客户端

Pro*_*ofK 9 c# security asp.net-identity asp.net-core-mvc asp.net-core

我有一个MVC Web应用程序,一个WPF客户端和Web API服务器.我非常想将API控制器拉入MVC应用程序,并且只有一个app/api.我的主要原因是为应用程序用户和API客户端提供一个登录过程.

我本来希望做的是将一个SignInManager<ApplicationUser注入Token控制器并使用

var result = await _signInManager.PasswordSignInAsync(login.Username, login.Password, false, false);
Run Code Online (Sandbox Code Playgroud)

使用与构建到MVC项目中相同的密码hasher来验证用户名和密码.我不想复制任何类型的功能.我也希望通过这种方式实现一个登录,为WPF应用程序提供JWT令牌,以访问API方面的内容,以及标准的登录cookie,以便正常的MVC应用程序请求获得授权.

我应该如何以最少的代码重复来解决这个问题?

IDEA: 使用一个MVC应用程序作为REST服务器.如果我Login获得JWT的操作也签署了我,例如_signInManager.PasswordSignInAsync,我也应该获得允许我在内部访问受保护动作的cookie,并在外部使用包含JWT的授权头.

Ale*_*ich 12

您可以考虑以下选项

选项#1:将MVC应用程序中使用的逻辑移动到新的类库,然后可以通过API项目引用它.这将允许您遵循SRP并在MVC和API应用程序中使用相同的逻辑.如果您想使ASP.NET身份相关的功能在MVC和API应用程序中很常见,请查看将ASP.NET身份模型移动到类库并按照提供的步骤操作.

选项#2:您可以将所有控制器和模型从API移动到MVC应用程序.您可以配置然后API控制器使用JWT身份验证方案并继续使用cookie身份验证方案fr MVC apps的控制器.如果要使用此方法,则需要配置身份验证中间件.例如,您的Startup类看起来像这样:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddMvc();

    services.AddAuthentication(o =>
    {
        o.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    }).AddCookie(options =>
    {
        options.AccessDeniedPath = new PathString("/Account/Login/");
        options.LoginPath = new PathString("/Account/Login/");
    }).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => {
        options.TokenValidationParameters = new TokenValidationParameters 
        {       
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("<put_your_secret_here>")),
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromMinutes(5)            
        };
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    app.UseAuthentication();
    app.UseMvcWithDefaultRoute();
    ...
}    
Run Code Online (Sandbox Code Playgroud)

然后,您可以定义BaseApiController哪些可用于设置到API控制器的路由并使用例如授权它们

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/[controller]")]
public abstract class BaseApiController {}
Run Code Online (Sandbox Code Playgroud)

并使所有API控制器继承此基本控制器.您还可以使用更灵活的基于策略的授权.完成后,您将能够使用MVC应用程序控制器中的cookie以及API控制器中的JWT令牌进行身份验证.

选项#3:您可以让API和MVC应用程序单独运行,并使用IdentityServer实现OAuth协议.将它添加到MVC应用程序,因为它与ASP.NET Identity完美集成并对其进行配置,以便继续使用MVC应用程序的cookie身份验证方案.然后配置其中一个OAuth流程以在WPF应用程序和API之间设置授权.IdentityServer有详细记录,并为其GitHub中的不同流提供样本.这种方法的优点是,即使您考虑添加更多必须使用相同用户群的API,SPA或MVC应用程序,您将来也不会遇到此类问题.此外,它还允许实现单点登录(SSO),因此如果您需要其他MVC应用程序,则可以轻松地将其集成到现有基础架构中.