JWT bearer token authorization being applied on exisitng MVC web appication in .NET Core

不想你离开。 提交于 2019-12-10 12:19:56

问题


I am trying out Web API's in .net core. I have added an API controller to my existing .net core MVC web application.

I am using JWT Tokens for authorization. I am doing this through the startup class.

The API works just fine.

But as expected the authorization is being applied on the entire MVC application.

Is there a way I can enable authentication through bearer tokens only for the API controllers and not the web application controllers?

Startup.cs:

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Project.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace Project
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }
        public bool ValidateAudience { get; private set; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity<IdentityUser,IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;

            });

            services.ConfigureApplicationCookie(options =>
            {
                options.Cookie.HttpOnly = true;
                options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
                options.LoginPath = "/Identity/Account/Login"; 
                options.LogoutPath = "/Identity/Account/Logout"; 
                options.AccessDeniedPath = "/Identity/Account/AccessDenied"; 
                options.SlidingExpiration = true;
            });

            services.AddCors();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddAuthentication(option =>
            {
                option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.SaveToken = true;
                options.RequireHttpsMetadata = true;
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidAudience = Configuration["Jwt:Site"],
                    ValidIssuer = Configuration["Jwt:Site"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SigningKey"]))
                };
            });

        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{Controller=Startup}/{action=Login}/{id?}");
            });
        }
    }
}

appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": " Data Source=Server; Database = db;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Jwt": {
    "Site": "www.signinkey.com",
    "SigningKey": "ConstantSigningKey",
    "ExpiryInMinutes": "30"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

API controller:

namespace Project.Controllers
{
    [Route("api/[controller]/[action]")]
    public class AuthController : BaseController
    {
        protected IConfiguration _configuration;

        public AuthController(UserManager<IdentityUser> userManager, IConfiguration configuration)
        {
            _userManager = userManager;
            _configuration = configuration;
        }

        public string GenerateToken(int size = 32)
        {
            var randomNumber = new byte[size];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(randomNumber);
                return Convert.ToBase64String(randomNumber);
            }
        }

        [HttpGet("")]
        [Route("modelList")]
        [Authorize]
        public IEnumerable<ModelList> SupervisorList(string username)
        {
             return db.modelList.Select(x => x).ToList();
        }

        [Route("register")]
        [HttpPost]
        public async Task<ActionResult> Register([FromBody] InputModel reg)
        {
            var user = new IdentityUser { UserName = reg.Email, Email = reg.Email, SecurityStamp = Guid.NewGuid().ToString() };
            var result = await _userManager.CreateAsync(user, reg.Password);
            if (result.Succeeded)
            {
                await _userManager.AddToRoleAsync(user, "Admin");
            }
            return Ok(new { Username = user.UserName });

        }

        [Route("login")]
        [HttpPost]
        public async Task<ActionResult> Login([FromBody] InputModel login)
        {
            var user = await _userManager.FindByNameAsync(login.Email);
            if (user != null && await _userManager.CheckPasswordAsync(user, login.Password))
            {

                var claim = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, user.UserName)
                };
                var signinKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SigningKey"]));

                int expiryInMinutes = Convert.ToInt32(_configuration["Jwt:ExpiryInMinutes"]);

                var token = new JwtSecurityToken(
                    issuer: _configuration["Jwt:Site"],
                    audience: _configuration["Jwt:Site"],
                    expires: DateTime.UtcNow.AddMinutes(expiryInMinutes),
                    signingCredentials: new SigningCredentials(signinKey, SecurityAlgorithms.HmacSha256)
                    );


                return Ok(
                    new
                    {
                        token = new JwtSecurityTokenHandler().WriteToken(token),
                        expiration = token.ValidTo
                    });


            }
            return Unauthorized();
        }
    }
}

As the JWT Token authentication is enabled in the startup class; I am getting an 401 unauthorized code when I try to access the non api controller actions as well.

What I am trying is:

  1. Add an API controller to an existing .net core mvc web application.
  2. Use JWT token authentication only for the API methods and not the web application methods.

    • Is the above possible? Is it a good practice? How can it be achieved?

Need Direction. Thank you:)


回答1:


Detailed Articles

Using Multiple Authentication/Authorization Providers in ASP.NET Core

Yes you can here are few steps

  1. Setup multiple authentication schemes in Startup.cs
  2. Use scheme as per controller
  3. Specify the Policy for web application and used that in Web app controllers [Authorize(Policy = "WebApp")]
  4. In Web API controllers just use the JWT authentication scheme

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Startup code

        .AddCookie(options =>
        {
            // You cookie auth setup 
        })
        .AddJwtBearer(options =>
        {
          // Your JWt setup
        })

policies Setup

services.AddAuthorization(options =>
        {
            options.AddPolicy("WebApp",
                              policy => policy.Requirements.Add(new WebAppRequirement()));
        });


来源:https://stackoverflow.com/questions/55115482/jwt-bearer-token-authorization-being-applied-on-exisitng-mvc-web-appication-in

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