NET Core 3.1 MVC Authorization/Authentication 带有在单独的 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
我有 3 个项目:
- Net Core 3.1 MVC 项目。
- 具有 JWT 身份验证的 Net Core 3.1 Web Api 项目 --> 通过 Entity Framework
连接到数据库
- (也使用网络 api 进行身份验证和数据检索的 Xamarin 应用程序)。
我不想从两个项目 (1,2) 分别连接到同一个数据库(感觉不是个好主意,如果我错了请纠正我,希望将数据库 crud 操作包含在网页 api).
我想在WebApi项目中做认证,把token传给Net Core MVC项目
我不知道如何使用令牌为该用户授权 MVC
项目,以便可以根据用户的角色访问控制器
等。基本上使用令牌将此用户登录到 MVC 项目中
在网络上获得 api。这甚至可能还是正确的方法?任何
请帮忙?
MVC 项目
Startup.csclass
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
}
}
这是您应该为您的应用程序实施 OAuth2.0 的典型场景 - 您有 2 种客户端(MVC 和 Xamrin),它们都需要经过身份验证然后才能访问您的 API 项目,您的 API 应该受到身份提供者的保护,而不是自己进行身份验证。在 asp.net core 中,最流行的解决方案是 Identity Server 4,您不必重新发明轮子,只需创建一个 Identity Provider 服务器,然后根据 API 配置您的 MVC 项目他们文件中的说明,然后一切正常。同时,Identity Server 4 支持 entity framework
嘿,我有解决方案,请参考以下要点
- 首先您需要添加身份验证。
public void ConfigureServices(IServiceCollection services)
services.AddSession();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["JWTConfig:ValidAudience"],
ValidIssuer = Configuration["JWTConfig:ValidIssuer"],
IssuerSigningKey = new >SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWTConfig:Secret"]))
};
});
- 之后,您必须使用 Session 来存储身份验证令牌,并且在这个令牌中,您必须加密角色列表的令牌组合,无论角色想要传递给授权。
Here i have used JWT Bearer token
- 使用此 session 您必须在
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
startup.cs 文件中配置以使用 header 身份验证。
app.UseSession();
app.Use(async (context, next) =>
{
var token = context.Session.GetString("Token");
if (!string.IsNullOrEmpty(token))
{
context.Request.Headers.Add("Authorization", "Bearer " + token);
}
await next();
});
- 然后你必须添加你的控制器
[Authorize(Roles = "Employee,Student")]
public ActionResult Leave()
{
// your code here
}
我有 3 个项目:
- Net Core 3.1 MVC 项目。
- 具有 JWT 身份验证的 Net Core 3.1 Web Api 项目 --> 通过 Entity Framework 连接到数据库
- (也使用网络 api 进行身份验证和数据检索的 Xamarin 应用程序)。
我不想从两个项目 (1,2) 分别连接到同一个数据库(感觉不是个好主意,如果我错了请纠正我,希望将数据库 crud 操作包含在网页 api).
我想在WebApi项目中做认证,把token传给Net Core MVC项目
我不知道如何使用令牌为该用户授权 MVC 项目,以便可以根据用户的角色访问控制器 等。基本上使用令牌将此用户登录到 MVC 项目中 在网络上获得 api。这甚至可能还是正确的方法?任何 请帮忙?
MVC 项目 Startup.csclass
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
}
}
这是您应该为您的应用程序实施 OAuth2.0 的典型场景 - 您有 2 种客户端(MVC 和 Xamrin),它们都需要经过身份验证然后才能访问您的 API 项目,您的 API 应该受到身份提供者的保护,而不是自己进行身份验证。在 asp.net core 中,最流行的解决方案是 Identity Server 4,您不必重新发明轮子,只需创建一个 Identity Provider 服务器,然后根据 API 配置您的 MVC 项目他们文件中的说明,然后一切正常。同时,Identity Server 4 支持 entity framework
嘿,我有解决方案,请参考以下要点
- 首先您需要添加身份验证。
public void ConfigureServices(IServiceCollection services)
services.AddSession(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; })
// Adding Jwt Bearer .AddJwtBearer(options => { options.SaveToken = true; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidateAudience = true, ValidAudience = Configuration["JWTConfig:ValidAudience"], ValidIssuer = Configuration["JWTConfig:ValidIssuer"], IssuerSigningKey = new >SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWTConfig:Secret"])) }; });
- 之后,您必须使用 Session 来存储身份验证令牌,并且在这个令牌中,您必须加密角色列表的令牌组合,无论角色想要传递给授权。
Here i have used JWT Bearer token
- 使用此 session 您必须在
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
startup.cs 文件中配置以使用 header 身份验证。
app.UseSession(); app.Use(async (context, next) => { var token = context.Session.GetString("Token"); if (!string.IsNullOrEmpty(token)) { context.Request.Headers.Add("Authorization", "Bearer " + token); } await next(); });
- 然后你必须添加你的控制器
[Authorize(Roles = "Employee,Student")] public ActionResult Leave() { // your code here }