首页 文章

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

提问于
浏览
32

我计划在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验证用户?

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

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

2 回答

  • 39

    为了让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) 
                    }
                });
            }
        }
    }
    

    您会注意到我将发行者,audienceId和audienceSecret放在我的Web.config文件中 . (这些值应与资源服务器上的值匹配) . 此外,您可能希望确保运行更新的System.IdentityModel.Tokens.Jwt:

    Update-package System.IdentityModel.Tokens.Jwt
    

    使用这些设置,您可以使用[Authorize]属性修饰控制器Action并播放球 .

    玩球当然意味着从你的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);
    

    UPDATE 顺便说一句,如果你想在你的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>
    

    ......当然,用自己的“ Value ”取代

  • 10

    我不知道你是否解决了这个问题,但我遇到了类似的问题,并决定使用FormsAuthentication存储令牌,我可以加密令牌,并在每次请求时将cookie传回,然后我可以将其解密为获取JWT,然后从中提取角色/声明,然后使用这些角色创建和Identity Principal,这将允许我使用[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)
    

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

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

相关问题