NET Core 3.1 MVC 授权/身份验证,带有在单独的 Net Core 3.1 Web Api 中从外部获取的令牌 (JWT)
Posted
技术标签:
【中文标题】NET Core 3.1 MVC 授权/身份验证,带有在单独的 Net Core 3.1 Web Api 中从外部获取的令牌 (JWT)【英文标题】:NET Core 3.1 MVC Authorization/Authentication with token (JWT) obtained externally in separate Net Core 3.1 Web Api 【发布时间】:2020-11-07 19:37:04 【问题描述】:我有 3 个项目:
-
Net Core 3.1 MVC 项目。
带有 JWT auth 的 Net Core 3.1 Web Api 项目 --> 通过 Entity Framework 连接到 db
(也使用 Web api 进行身份验证和数据检索的 Xamarin 应用程序)。
我不想从两个项目 (1,2) 分别连接到同一个数据库(感觉不是一个好主意,如果我错了,请纠正我,希望将 db crud 操作包含在 web api 中)。
我想在 Web Api 项目中进行身份验证并将令牌传递给 Net Core MVC 项目。
我不知道如何使用令牌授权此用户进行 MVC 项目,以便可以根据用户的角色访问控制器 等基本上用令牌将此用户登录到MVC项目中 在 web api 中获得。这甚至可能还是正确的方法?任何 请帮忙?
MVC 项目 Startup.cs 类
public class Startup
public Startup(IConfiguration configuration)
Configuration = configuration;
public IConfiguration Configuration get;
public void ConfigureServices(IServiceCollection services)
// add for razor pages and refresh without rebuilding
services.AddRazorPages().AddRazorRuntimeCompilation();
// add httpClient
services.AddHttpClient();
// start auth jwt
services.AddSession(options =>
options.IdleTimeout = TimeSpan.FromMinutes(1);
);
//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//Provide a secret key to Encrypt and Decrypt the Token
var SecretKey = Encoding.ASCII.GetBytes
("mySecretKeyForAuthenticationAndAuthorization");
//Configure JWT Token Authentication
services.AddAuthentication(auth =>
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(token =>
token.RequireHttpsMetadata = false;
token.SaveToken = true;
token.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
//Same Secret key will be used while creating the token
IssuerSigningKey = new SymmetricSecurityKey(SecretKey),
ValidateIssuer = true,
//Usually, this is your application base URL
ValidIssuer = "https://myAzureWebAPi.azurewebsites.net",
ValidateAudience = true,
//Here, we are creating and using JWT within the same application.
//In this case, base URL is fine.
//If the JWT is created using a web service, then this would be the consumer URL.
ValidAudience = "https://mylocalhost/",
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
;
);
// end auth jwt
// add for roles authorization
services.AddAuthorization(config =>
config.AddPolicy(Policies.Admin, Policies.AdminPolicy());
config.AddPolicy(Policies.Client, Policies.ClientPolicy());
);
services.AddControllersWithViews();
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
//add for jwt
app.UseCookiePolicy();
app.UseSession();
//Add JWToken to all incoming HTTP Request Header
app.Use(async (context, next) =>
var JWToken = context.Session.GetString("JWToken");
if (!string.IsNullOrEmpty(JWToken))
context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
await next();
);
app.UseRouting();
// added for jwt
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllerRoute(
name: "default",
pattern: "area=Client/controller=LoginPage/action=Index/id?");
);
MVC LoginPageController.cs
[Area("Client")]
public class LoginPageController : Controller
private readonly IHttpClientFactory _clientFactory;
public LoginPageController(IHttpClientFactory clientFactory)
_clientFactory = clientFactory;
public IActionResult Index()
return View();
[HttpPost]
public async Task<IActionResult> Login([Bind] LoginModel loginModel)
var client = _clientFactory.CreateClient();
//var client = new HttpClient();
try
var json = JsonConvert.SerializeObject(loginModel);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var outcome = await client.PostAsync("https://<AzureWebAPiUrl>/api/accounts/login", content);
if (outcome!= null && outcome.IsSuccessStatusCode)
var jsonResult = await outcome.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<Token>(jsonResult);
Console.WriteLine(token.user_role);
// store token in a session
HttpContext.Session.SetString("JWToken", token.access_token);
// Here is the problem, once I have the token how do I make this user be
//authenticated in the mvc project so that the [Authorize[Role = "someRole"] on controllers works
catch (Exception ex)
Console.WriteLine(ex.Message);
return RedirectToAction("Index", "AdminDeals", new area = "Admin"); // only if role is admin
【问题讨论】:
【参考方案1】:这是您应该为您的应用程序实现 OAuth2.0 的典型场景 - 您有 2 种客户端(MVC 和 Xamrin),它们都需要经过身份验证才能访问您的 API 项目,您的 API 应该受到保护身份提供者,而不是自己进行身份验证。在 asp.net core 中,最流行的解决方案是Identity Server 4,你不必重新发明***,只需创建一个身份提供程序服务器,然后根据文档中的说明配置你的 API 和 MVC 项目,一切正常然后。同时,Identity Server 4 支持实体框架
【讨论】:
一个可靠的建议,谢谢,将在 IdentityServer4 上探索更多以上是关于NET Core 3.1 MVC 授权/身份验证,带有在单独的 Net Core 3.1 Web Api 中从外部获取的令牌 (JWT)的主要内容,如果未能解决你的问题,请参考以下文章
.Net Core 2.1 WepAPI 中使用 JWT 的身份验证和授权
.NET Core - 在 IIS 上使用 Windows 身份验证从 MVC 应用程序调用 Web API 导致 HttpRequestException 401(未经授权)状态代码
用户授权 - 为用户分配授权策略 .Net Core 3.1
ASP.NET Core 3.1 MVC AddOpenIDConnect 与 IdentityServer3