Tai*_*T's 4 c# authentication jwt asp.net-core-mvc asp.net-core-2.2
我有一个 .Net Core 2.2 Web 应用程序 MVC,我在其中添加了 API 控制器和 SignalR 集线器。另一方面,我有一个调用集线器方法的移动应用程序。在从应用程序调用集线器之前,我通过 API 调用对我的用户进行身份验证 - 取回 JWT 令牌 - 并将此令牌用于未来的请求,这样我就可以Context.User.Identity.Name在我的集线器方法中使用:
public static async Task<string> GetValidToken(string userName, string password)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_API_BASE_URI);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
LoginViewModel loginVM = new LoginViewModel() { Email = userName, Password = password, RememberMe = false };
var formContent = Newtonsoft.Json.JsonConvert.SerializeObject(loginVM);
var content = new StringContent(formContent, Encoding.UTF8, "application/json");
HttpResponseMessage responseMessage;
try
{
responseMessage = await client.PostAsync("/api/user/authenticate", content);
var responseJson = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); ;
var jObject = JObject.Parse(responseJson);
_TOKEN = jObject.GetValue("token").ToString();
return _TOKEN;
}catch
[...]
Run Code Online (Sandbox Code Playgroud)
然后使用令牌:
_connection = new HubConnectionBuilder().WithUrl(ApiCommunication._API_BASE_URI + "/network", options =>
{
options.AccessTokenProvider = () => Task.FromResult(token);
}).Build();
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好。它在我的移动应用程序上按预期工作。但是为了使它工作,我必须在服务器端(Startup.cs)设置这段代码:
services.AddAuthentication(options =>
{
options .DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options .DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
...
Run Code Online (Sandbox Code Playgroud)
这阻止我再使用 cookie 身份验证,因此 mvc Web 应用程序不再按预期工作,因为它无法在请求中获取当前经过身份验证的用户。
删除行:
options .DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options .DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
Run Code Online (Sandbox Code Playgroud)
使网络应用程序正常工作,但不再是移动应用程序(由于Context.User.Identity.Name等于 null,集线器调用失败)。
我一直在四处寻找如何处理不同的方案(在我的情况下是 cookie + jwt),据我所知,这是设计使然不再可能。
是否有任何可能的解决方法来使用双重方案还是我遗漏了什么?
我想也许我应该托管 2 个单独的项目,一个使用 Cookie 身份验证,另一个使用 JWT?
提前致谢。
有多种方法可以解决您遇到的问题,但首先让我们了解一下它目前不起作用的原因。
DefaultAuthenticateScheme意思当您为 的DefaultAuthenticateScheme属性设置一个值时AuthenticationOptions,您指示身份验证中间件尝试根据该特定方案对每个 HTTP 请求进行身份验证。我将假设您使用 ASP.NET Identity 进行基于 cookie 的身份验证,并且当您调用 时AddIdentity,它会将 cookie 身份验证方案注册为用于身份验证的默认方案;您可以在 GitHub 上的源代码中看到这一点。
但是,这并不意味着您不能在应用程序中使用任何其他身份验证方案。
如果您的应用程序的所有受保护端点都可供使用 cookie 或 JWT 进行身份验证的客户端访问,则一种选择是使用授权系统默认策略。当您使用AuthorizeAttribute该类的“空”实例时,将使用该特殊策略- 作为装饰控制器/操作的属性,或在应用程序级别全局使用new AuthorizeFilter(new AuthorizeAttribute()).
默认策略设置为仅需要经过身份验证的用户,但未定义需要“尝试”哪些身份验证方案来对请求进行身份验证。结果是它依赖于已经执行的身份验证过程。它解释了您遇到的行为,其中一次只有两种方案中的一种有效。
我们可以使用一些代码更改默认策略:
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("<your-cookie-authentication-scheme", "your-jwt-authentication-scheme")
.Build();
})
Run Code Online (Sandbox Code Playgroud)
如果您发现自己需要某些端点只能由使用 cookie 进行身份验证的客户端访问,而其他端点可以通过 JWT 访问,您可以利用授权策略。
它们的工作方式与默认策略完全相同,希望您可以根据端点选择哪个适用。您可以添加如下策略:
services.AddAuthorization(options =>
{
options.AddPolicy("Cookies", new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("<your-cookie-authentication-scheme")
.Build());
options.AddPolicy("JWT", new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("<your-jwt-authentication-scheme")
.Build());
})
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过用 装饰它们在适当的端点中引用这些策略[Authorize(Policy = "<policy-name>")]。附带说明一下,如果您的策略之间的唯一区别是身份验证方案,则可以在不创建策略的情况下实现相同的结果,并在[Authorize]属性中引用适当的身份验证方案AuthenticationSchemes。
当您有更复杂的规则时,策略很有价值,例如特定声明需要此特定值。
我希望这会有所帮助,让我知道你的去向!
| 归档时间: |
|
| 查看次数: |
1112 次 |
| 最近记录: |