C# 如何在MVC应用程序中使用JWT进行身份验证和授权?

C# 如何在MVC应用程序中使用JWT进行身份验证和授权?,c#,asp.net-mvc-4,authentication,authorization,asp.net-identity,C#,Asp.net Mvc 4,Authentication,Authorization,Asp.net Identity,我计划在ASP.NET MVC应用程序中使用ASP.NET Identity 2.0进行身份验证和授权 参考下面的链接 我能够为有效用户创建访问令牌(JWT),即,当用户登录到应用程序时,我将使用名称和密码验证用户,然后我将为该有效用户发布JSON web令牌 现在,我在一些文章中读到,我们需要在每个请求的头中传递承载令牌,以验证用户的身份验证。在MVC中,我们将为需要保护的方法提供Authorize属性,如下所示 public class UserController : Bas

我计划在ASP.NET MVC应用程序中使用ASP.NET Identity 2.0进行身份验证和授权

参考下面的链接

我能够为有效用户创建访问令牌(JWT),即,当用户登录到应用程序时,我将使用名称和密码验证用户,然后我将为该有效用户发布JSON web令牌

现在,我在一些文章中读到,我们需要在每个请求的头中传递承载令牌,以验证用户的身份验证。在MVC中,我们将为需要保护的方法提供Authorize属性,如下所示

      public class UserController : BaseHRAppController
      {
            [Authorize]
            public ActionResult Index()
            {          
               return View();
            }
       }
如何告诉我的MVC应用程序使用JWT验证用户

我想让我的MVC应用程序在用户尝试访问带有authorize属性的方法时使用JWT验证用户。因为我将在许多页面中使用AJAX调用来访问MVC控制器中存在的方法,所以我认为在每个AJAX请求上传递一个令牌并不好。我需要帮助在MVC应用程序中使用ASP.NET标识以高效的方式完成身份验证和授权


目前,我不知道如何在MVC应用程序中使用此JWT令牌进行身份验证和授权。

我不知道您是否解决了这个问题,但我遇到了一个类似的问题,决定使用FormsAuthentication存储令牌,我能够对令牌进行加密,在每次请求时,cookie都会被传回,然后我可以解密它以获得JWT,然后从中提取角色/声明,然后使用这些角色创建和标识主体,这将允许我用[Authorize(Role=“blah,blah”)]装饰我的控制器方法

下面是一些示例代码

登录后从api获取JSON web令牌后,您可以使用以下内容:

var returnedToken = (TokenResponse)result.ReturnedObject;
var ticket = new FormsAuthenticationTicket(1, model.Email, DateTime.Now, ConvertUnitToDateTime(returnedToken.expires_in), true, returnedToken.access_token);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie)
using System.Configuration;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Jwt;
using Owin;

[assembly: OwinStartupAttribute(typeof(TOMS.Frontend.Startup))]
namespace TOMS.Frontend
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            ConfigureOAuthTokenConsumption(app);
        }

        private void ConfigureOAuthTokenConsumption(IAppBuilder app)
        {
            var issuer = ConfigurationManager.AppSettings["Issuer"];
            var audienceId = ConfigurationManager.AppSettings["AudienceId"];
            var audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);

            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                AllowedAudiences = new[] { audienceId },
                IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                {
                    new SymmetricKeyIssuerSecurityTokenProvider(issuer, audienceSecret) 
                }
            });
        }
    }
}
这里有一些我自己创建的类和方法,但它会让您大致了解将JWT访问令牌以及过期日期存储在FormsAuthenticationCookie中

然后,cookie随每个请求一起传递,在Global.asax文件中,您可以使用一种方法来验证请求:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        JwtSecurityToken jwTok = TokenHelper.GetJWTokenFromCookie(authCookie); 

        // Create the IIdentity instance
        IIdentity id = new FormsIdentity(authTicket);

        // Create the IPrinciple instance
        IPrincipal principal = new GenericPrincipal(id, TokenHelper.GetRolesFromToken(jwTok).ToArray());

        // Set the context user
        Context.User = principal;
    }
}
因此,该方法将解密cookie以获取JWT访问令牌,然后可以使用Microsoft的System.IdentityModel.Tokens.JWT库对其进行解码,然后获取这些角色和ID,并为用户生成主体和标识,从而创建具有这些角色的用户


然后可以根据[Authorize]属性验证这些角色。

为了让MVC了解JWT的任何信息,您基本上必须告诉它:-)。首先,从nuget安装Jwt包:

Install-Package Microsoft.Owin.Security.Jwt
然后打开Startup.cs文件,添加一个新函数,告诉MVC如何使用JWT。基本上,你的创业公司看起来像:

var returnedToken = (TokenResponse)result.ReturnedObject;
var ticket = new FormsAuthenticationTicket(1, model.Email, DateTime.Now, ConvertUnitToDateTime(returnedToken.expires_in), true, returnedToken.access_token);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie)
using System.Configuration;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Jwt;
using Owin;

[assembly: OwinStartupAttribute(typeof(TOMS.Frontend.Startup))]
namespace TOMS.Frontend
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            ConfigureOAuthTokenConsumption(app);
        }

        private void ConfigureOAuthTokenConsumption(IAppBuilder app)
        {
            var issuer = ConfigurationManager.AppSettings["Issuer"];
            var audienceId = ConfigurationManager.AppSettings["AudienceId"];
            var audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);

            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                AllowedAudiences = new[] { audienceId },
                IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                {
                    new SymmetricKeyIssuerSecurityTokenProvider(issuer, audienceSecret) 
                }
            });
        }
    }
}
您会注意到,我正在我的Web.config文件中放置发行人audenceId和audenceCret。(这些值应与资源服务器上的值匹配)。此外,您可能希望确保运行更新的System.IdentityModel.Tokens.Jwt:

Update-package System.IdentityModel.Tokens.Jwt
设置这些属性后,您可以使用[Authorize]属性装饰控制器操作并玩球

“玩球”当然意味着从javascript向受保护的控制器操作发出请求:

//assuming you placed the token in a sessionStorage variable called tokenKey when it came back from your Authorization Server
    var token = sessionStorage.getItem(tokenKey);
    var headers = {};
    if (token) {
        headers.Authorization = 'Bearer ' + token;
    }

    $.ajax({
        type: 'GET',
        url: 'CONTROLLER/ACTION',
        headers: headers
    }).done(function (data) {
        self.result(data);
    }).fail(showError);
更新 顺便说一句,如果您希望在web.config文件中添加值,以便像我上面所做的那样检索它们;只需将它们添加到AppSettings下:

<configuration>
 <appSettings>
    <add key="Issuer" value="YOUR_ISSUER" />
    <add key="AudienceId" value="YOUR_AUDIENCEID" />
    <add key="AudienceSecret" value="YOUR_AUDIENCESECRET" />
 </appSettings>
</configuration>


…当然,用你自己的来取代“价值观”

这方面运气好吗?我认为对于MVC应用程序,您必须使用cookies,我不确定这一点,但它似乎是如何工作的。VS中的SPA模板使用两种形式的身份验证:MVC的Cookie和Web API的token有一个问题:这种方法能保护您免受CSRF攻击吗?嘿@reverence12389,假设您没有TokenHelper代码可用吗?如果您通过JWT取回您的token,然后你可以看看我对一个类似问题的回答:@HoudiniSutherland伟大的答案。如何将其与标准cookie身份验证相结合?我有一个带有普通控制器的MVC5项目,它受
Authorize
属性保护,并使用cookie。但我还添加了一些我想用JWT保护的APIController。如何使cookies用于普通控制器,JWT用于Api控制器?@emzero请查看Shawn的文章,该文章应该让您设置并运行。希望能有所帮助:@HoudiniSutherland不幸的是,这是针对ASP.NET核心的(就像大多数关于此的文章一样)。我似乎找不到一个适用于普通的旧ASP.NET MVC 5。@HoudinisAutherland哪里是
ConfigureAuth()
implementation?我们应该默认使用它还是添加一些与JWT相关的配置行。你能把这个方法添加到你的答案中吗?谢谢