结合使用MVC页面和Web API页面的身份验证?

Bri*_*ice 23 cookies asp.net-mvc asp.net-web-api bearer-token

我有一个MVC 5 Web应用程序,可以使用Login.cshtml页面登录并获取cookie并且登录正常.但是,我想使用Web API进行登录,然后(可能)设置一个cookie,以便我登录我的MVC页面...(或使用MVC登录登录然后访问Web API)但是web api返回一个bearer token而不是cookie令牌...所以这不起作用.有没有办法结合使用我的MVC页面和我的Web API页面的身份验证?

更新:

这不是一个真正的代码问题,而是一个概念问题.

普通的MVC网页会检查一个名为".AspNet.ApplicationCookie"的cookie,以确定请求者的身份.通过调用ApplicationSignInManager.PasswordSignInAsync生成此cookie.

另一方面,WebAPI调用检查名为Authorization的项目的请求标头...并使用该值来确定请求者标识.这是从WebAPI调用"/ Token"返回的.

这些是非常不同的价值观.我的网站需要同时使用MVC页面 WebAPI调用(以动态更新这些页面)......并且都需要进行身份验证才能执行其任务.

我能想到的唯一方法是实际验证两次......一次是使用WebAPI调用,另一次是使用Login帖子.(见下面的答案).

这似乎非常hacky ...但我不明白授权代码足以知道是否有更合适的方法来实现这一点.

Rav*_* A. 10

实现此目标的最佳方法是在MVC项目中拥有授权服务器(生成令牌的Web API)和令牌消费中间件.IdentityServer应该有所帮助.不过我这样做了:

我使用JWT使用Web API和ASP.Net身份作为解释建立了一个授权服务器在这里.

完成后,您的Web API startup.cs将如下所示:

 // Configures cookie auth for web apps and JWT for SPA,Mobile apps
 private void ConfigureOAuthTokenGeneration(IAppBuilder app)
 {
    // Configure the db context, user manager and role manager to use a single instance per request
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

    // Cookie for old school MVC application
    var cookieOptions = new CookieAuthenticationOptions
    {
        AuthenticationMode = AuthenticationMode.Active,
        CookieHttpOnly = true, // JavaScript should use the Bearer
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,                
        LoginPath = new PathString("/api/Account/Login"),
        CookieName = "AuthCookie"
    };
    // Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
    app.UseCookieAuthentication(cookieOptions);

    OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        //For Dev enviroment only (on production should be AllowInsecureHttp = false)
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/oauth/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
        Provider = new CustomOAuthProvider(),                
        AccessTokenFormat = new CustomJwtFormat(ConfigurationManager.AppSettings["JWTPath"])
    };

    // OAuth 2.0 Bearer Access Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到CustomOAuthProviderCustomJwtFormat课程.

我在我想要使用相同令牌保护的所有其他API(资源服务器)中编写了一个消费逻辑(即中间件).由于您希望在MVC项目中使用Web API生成的令牌,因此在实现授权服务器之后,您需要执行以下操作:

在您的MVC应用中,将其添加到startup.cs:

public void Configuration(IAppBuilder app)
{
        ConfigureOAuthTokenConsumption(app);
}

private void ConfigureOAuthTokenConsumption(IAppBuilder app)
{
    var issuer = ConfigurationManager.AppSettings["AuthIssuer"];
    string audienceid = ConfigurationManager.AppSettings["AudienceId"];
    byte[] audiencesecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);

    app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieName = "AuthCookie" , AuthenticationType=DefaultAuthenticationTypes.ApplicationCookie });

    //// Api controllers with an [Authorize] attribute will be validated with JWT
    app.UseJwtBearerAuthentication(
        new JwtBearerAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Passive,
            AuthenticationType = "JWT",
            AllowedAudiences = new[] { audienceid },
            IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
            {
                new SymmetricKeyIssuerSecurityTokenProvider(issuer, audiencesecret)                           
            }

        });
}
Run Code Online (Sandbox Code Playgroud)

在MVC控制器中,当您收到令牌时,对其进行反序列化并从访问令牌生成cookie:

AccessClaims claimsToken = new AccessClaims();
claimsToken = JsonConvert.DeserializeObject<AccessClaims>(response.Content);
claimsToken.Cookie = response.Cookies[0].Value;               
Request.Headers.Add("Authorization", "bearer " + claimsToken.access_token);
var ctx = Request.GetOwinContext();
var authenticateResult = await ctx.Authentication.AuthenticateAsync("JWT");
ctx.Authentication.SignOut("JWT");
var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(applicationCookieIdentity);
Run Code Online (Sandbox Code Playgroud)

生成机器密钥并将其添加到web.configWeb API和ASP.Net MVC站点中.

这样,将创建一个cookie [Authorize],MVC站点和Web API中的属性将遵循此cookie.

PS我有一个Web API发出智威汤逊(授权服务器或验证和资源服务器)做到了这一点,并能使用它在一个ASP.Net MVC的网站,SPA网站建在建在蟒蛇(资源服务器)角,安全的API, spring(资源服务器)和Android App.