JWT 不记名令牌授权应用于 .NET Core 中的现有 MVC Web 应用程序
Posted
技术标签:
【中文标题】JWT 不记名令牌授权应用于 .NET Core 中的现有 MVC Web 应用程序【英文标题】:JWT bearer token authorization being applied on exisitng MVC web appication in .NET Core 【发布时间】:2019-08-02 13:42:46 【问题描述】:我正在 .net 核心中试用 Web API。我已将 API 控制器添加到现有的 .net 核心 MVC Web 应用程序中。
我正在使用 JWT 令牌进行授权。我是通过启动类来做这个的。
API 工作正常。
但正如预期的那样,授权正在应用于整个 MVC 应用程序。
有没有一种方法可以通过不记名令牌启用身份验证,仅适用于 API 控制器,而不适用于 Web 应用程序控制器?
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 控制器:
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();
由于在启动类中启用了 JWT Token 认证;当我尝试访问非 api 控制器操作时,我也收到了 401 未经授权的代码。
我正在尝试的是:
-
将 API 控制器添加到现有的 .net core mvc Web 应用程序。
仅对 API 方法使用 JWT 令牌身份验证,而不是 Web 应用程序方法。
以上可能吗?这是一个好习惯吗?如何实现?需要方向。谢谢:)
【问题讨论】:
【参考方案1】:您可以在 .NET 中编写自己的授权属性。像 [CustomAuthorization]
而不是内置的属性器。当然是学习阶段。
【讨论】:
【参考方案2】:详细文章
Using Multiple Authentication/Authorization Providers in ASP.NET Core
是的,您可以在这里执行几个步骤
-
在 Startup.cs 中设置多个身份验证方案
按控制器使用方案
为 Web 应用程序指定策略并在 Web 应用程序控制器中使用该策略
[Authorize(Policy = "WebApp")
]
在 Web API 控制器中,只需使用 JWT 身份验证方案
[授权(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
启动代码
.AddCookie(options =>
// You cookie auth setup
)
.AddJwtBearer(options =>
// Your JWt setup
)
政策设置
services.AddAuthorization(options =>
options.AddPolicy("WebApp",
policy => policy.Requirements.Add(new WebAppRequirement()));
);
【讨论】:
以上是关于JWT 不记名令牌授权应用于 .NET Core 中的现有 MVC Web 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
在 ASP.NET Core 2.1 Web 客户端中存储不记名令牌的位置
JWT 不记名令牌不适用于 ASP.Net Core 3.1 + Identity Server 4
ASP.NET Core API 使用 JWT 不记名令牌进行身份验证
.Net Core 2.1 过期的 JWT 令牌响应 [发布与获取]