【问题标题】:How to use JWT in MVC application for authentication and authorization?如何在 MVC 应用程序中使用 JWT 进行身份验证和授权?
【发布时间】:2015-06-29 18:04:13
【问题描述】:

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

参考以下链接

JSON Web Token in ASP.NET Web API 2 using Owin

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

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

      public class UserController : BaseHRAppController
      {
            [Authorize]
            public ActionResult Index()
            {          
               return View();
            }
       }

如何告诉我的 MVC 应用程序使用 JWT 来验证用户?

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

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

【问题讨论】:

  • 运气好吗?我认为对于 MVC 应用程序,您必须使用 cookie,我不确定这一点,但它似乎是如何工作的。 VS 中的 SPA 模板使用 2 种形式的身份验证:MVC 的 cookie 和 Web API 的令牌

标签: c# asp.net-mvc-4 authentication authorization asp.net-identity


【解决方案1】:

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

Install-Package Microsoft.Owin.Security.Jwt

然后打开您的 Startup.cs 文件并添加一个新函数,该函数将告诉 MVC 如何使用 JWT。在基础上,您的 Startup 将类似于:

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 文件中放置了颁发者、受众 ID 和受众秘密。 (这些值应该与您的资源服务器上的值匹配)。此外,您可能希望确保运行更新的 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>

...当然,用你自己的替换“值”

【讨论】:

  • 如果您通过 JWT 取回您的令牌,那么您可以查看我对类似问题的回答:stackoverflow.com/questions/29271314/…
  • @HoudiniSutherland 很好的答案。您如何将其与标准 cookie 身份验证相结合?我有一个带有普通控制器的 MVC 5 项目,该控制器受 Authorize 属性保护并使用 cookie。但我还添加了一些我想用 JWT 保护的 ApiController。我怎样才能让它用于普通控制器和 JWT 用于 Api 控制器?
  • @emzero 查看 Shawn 的文章,它应该让您进行设置和使用。希望对您有所帮助:wildermuth.com/2017/08/19/…
  • @HoudiniSutherland 不幸的是,这是针对 ASP.NET Core 的(就像大多数关于此的文章一样)。我似乎无法为普通的旧 ASP.NET MVC 5 找到一个。
  • @HoudiniSutherland ConfigureAuth() 的实现在哪里?我们应该默认使用它还是向 JWT 添加一些配置行。您能否将此方法添加到您的答案中?谢谢。
【解决方案2】:

我不知道你是否解决了这个问题,但我遇到了类似的问题并决定使用我能够加密令牌的 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)

我有一些我自己创建的类和方法,但它会让您大致了解您将 JWT 访问令牌以及到期日期存储在 FormsAuthentication cookie 中。

然后 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] 属性验证这些角色。

【讨论】:

  • 有一个问题:这种方法可以保护您免受 CSRF 攻击吗?
  • 嘿@reverence12389,你没有可用的TokenHelper代码吗?
猜你喜欢
  • 2017-04-15
  • 2018-03-12
  • 2019-09-23
  • 1970-01-01
  • 2014-09-05
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多