.NET Framework MVC and Web Api Auth JWT

夙愿已清 提交于 2020-06-11 18:39:11

问题


I have a project in MVC using .NET Framework v4.7 with some WebApi on it. What I need to know is how to use a middleware between then to authorize a JWT for HTTP requests and MVC Action requests.

I've searched everywhere looking for a solution sample, but I couldn't find anything.

If anyone could help, I would be grateful.

Sorry for the English.


回答1:


If I grasped your problem statement, I think OWIN might be an option: you decouple your application from underlying hosting and get an extensible pipeline that you can inject middleware into (pretty much like .net core works out of the box).

Even better - it comes with JWT support out of the box (well, you need to install a few nuget packages - see below). Then you simply enable it on your IAppBuilder and roll with standard [Authorize] attributes.

To demo this setup, I've put together a working GitHub repo here to illustrate WebApi middleware.

Apart from Microsoft.AspNet.WebApi.Owin, Microsoft.Owin.Host.SystemWeb and Microsoft.Owin.Security.Jwt nuget packages, it's pretty much a stock standard asp.net WebApi project with the following files changed:

/Startup.cs

using System.Text;
using System.Web.Http;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Jwt;
using Owin;

namespace OWIN.WebApi
{
    public class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = new HttpConfiguration();
            WebApiConfig.Register(config); // bootstrap your existing WebApi config 

            appBuilder.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateIssuerSigningKey = true, // I guess you don't even have to sign the token
                    ValidIssuer = "http://localhost",
                    ValidAudience = "http://localhost",
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("jwt_signing_secret_key"))
                }
            });
            appBuilder.UseWebApi(config); // instruct OWIN to take over
        }
    }
}

/Controllers/ProtectedValuesController.cs

using System.Collections.Generic;
using System.Web.Http;

namespace OWIN.WebApi.Controllers
{
    [Authorize]
    public class ProtectedValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
    }
}

/Controllers/ObtainJwtController.cs

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Web.Http;
using Microsoft.IdentityModel.Tokens;
using Claim = System.Security.Claims.Claim;

namespace OWIN.WebApi.Controllers
{
    // this class is literally just a test harness to help me generate a valid token for popping into Postman.
    public class ObtainJwtController: ApiController
    {
        private string CraftJwt()
        {
            string key = "jwt_signing_secret_key"; //Secret key which will be used later during validation    
            var issuer = "http://localhost";

            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var permClaims = new List<Claim>
            {
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim("valid", "1"),
                new Claim("userid", "1"),
                new Claim("name", "test")
            };

            var token = new JwtSecurityToken(issuer,
                issuer,
                permClaims,
                expires: DateTime.Now.AddDays(1),
                signingCredentials: credentials);
            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        public string Get()
        {
            return $"Bearer {CraftJwt()}";
        }
    }
}

This appears to work for MVC too

I have added a few extra nuget packages to do with ASP.NET Identity, which seems to have enabled me to successfully protect the following controller:

/Controllers/Home.cs

using System.Web.Mvc;

namespace OWIN.WebApi.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Title = "Home Page";

            return View();
        }

        [Authorize]
        public ActionResult Protected()
        {
            return View();
        }
    }
}

Hopefully that gives you some options to explore




回答2:


See what I understand from your question You want to use JWT Token for your WebApi and normal process for your MVC, as for later View generated from server and its not dependent on JWT Token.

I have seen this problem. In one of my application I am hosting both MVC views and webapi, whereas MVC view rely on cookie based authentication and authorization. and WebApi call depend upon JWT token for authorization and authentication.

Sorry this solution is from .net core. you need to configure both Cookie and JWT authentication like this

services.AddCookie()
.AddJwtBearer()

Here default would be your cookie authentication. Now to enable jwt token for your webapi you need to decorate webapi with following attribute

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Hope that's answer your question.



来源:https://stackoverflow.com/questions/52449799/net-framework-mvc-and-web-api-auth-jwt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!