max*_*ini 19 .net c# asp.net authentication asp.net-core-2.0
我在VS17中使用"Web应用程序(模型 - 视图 - 控制器)"模板和".Net Framework"+"ASP.NET Core 2"作为配置创建了一个新的ASP.NET核心Web应用程序项目.身份验证配置设置为"个人用户帐户".
我有以下示例端点:
[Produces("application/json")]
[Route("api/price")]
[Authorize(Roles = "PriceViwer", AuthenticationSchemes = "Cookies,Bearer")]
public class PriceController : Controller
{
public IActionResult Get()
{
return Ok(new Dictionary<string, string> { {"Galleon/Pound",
"999.999" } );
}
}
Run Code Online (Sandbox Code Playgroud)
"Cookies,Bearer"
是通过连接CookieAuthenticationDefaults.AuthenticationScheme
和派生而得到的JwtBearerDefaults.AuthenticationScheme
.
目标是能够为端点配置授权,以便可以使用令牌和cookie身份验证方法访问它.
以下是我在Startup.cs中进行身份验证的设置:
services.AddAuthentication()
.AddCookie(cfg => { cfg.SlidingExpiration = true;})
.AddJwtBearer(cfg => {
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters() {
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
};
});
Run Code Online (Sandbox Code Playgroud)
因此,当我尝试使用浏览器访问端点时,我得到了一个带有空白html页面的401响应.
然后我登录,当我再次尝试访问端点时,我得到相同的响应.
然后,我尝试通过指定承载令牌来访问端点.并且返回200响应所需的结果.
那么,如果我删除[Authorize(AuthenticationSchemes = "Cookies,Bearer")]
,情况就会相反 - cookie身份验证工作并返回200,但是上面使用的相同的承载令牌方法不会给出任何结果,只是重定向到默认的AspIdentity登录页面.
我在这里可以看到两个可能的问题:
1)ASP.NET Core不允许"组合"身份验证.2)'Cookies'不是有效的模式名称.但那么正确的使用方法是什么?
请指教.谢谢.
Dav*_*and 20
如果我正确理解了这个问题,那么我相信有一个解决方案。在以下示例中,我在单个应用程序中使用 cookie 和不记名身份验证。该[Authorize]
属性可以在不指定方案的情况下使用,应用程序将根据所使用的授权方法动态做出反应。
services.AddAuthentication
被调用两次以注册 2 个身份验证方案。解决方案的关键是services.AddAuthorization
代码片段末尾的 调用,它告诉 ASP.NET 使用 BOTH 方案。
我已经对此进行了测试,它似乎运行良好。
(基于Microsoft 文档。)
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = "https://localhost:4991";
options.RequireHttpsMetadata = false;
options.ClientId = "WebApp";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.Scope.Add("api");
options.SaveTokens = true;
});
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:4991";
options.RequireHttpsMetadata = false;
// name of the API resource
options.Audience = "api";
});
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CookieAuthenticationDefaults.AuthenticationScheme,
JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
Run Code Online (Sandbox Code Playgroud)
编辑
这适用于经过身份验证的用户,但如果用户尚未登录,则仅返回 401(未经授权)。
为确保将未经授权的用户重定向到登录页面,请将以下代码添加到Configure
Startup 类中的方法中。注:这是至关重要的是,新的中间件放置后的呼叫app.UseAuthentication()
。
app.UseAuthentication();
app.Use(async (context, next) =>
{
await next();
var bearerAuth = context.Request.Headers["Authorization"]
.FirstOrDefault()?.StartsWith("Bearer ") ?? false;
if (context.Response.StatusCode == 401
&& !context.User.Identity.IsAuthenticated
&& !bearerAuth)
{
await context.ChallengeAsync("oidc");
}
});
Run Code Online (Sandbox Code Playgroud)
如果您知道实现此重定向的更简洁的方法,请发表评论!
Nik*_*aus 10
我认为您不需要将AuthenticationScheme设置为Controller.只需在ConfigureServices中使用Authenticated用户,如下所示:
// requires: using Microsoft.AspNetCore.Authorization;
// using Microsoft.AspNetCore.Mvc.Authorization;
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
Run Code Online (Sandbox Code Playgroud)
有关我的资源的文档:registerAuthorizationHandlers
对于该部分,无论scheme-Key是否无效,您都可以使用插值字符串来使用正确的键:
[Authorize(AuthenticationSchemes = $"{CookieAuthenticationDefaults.AuthenticationScheme},{JwtBearerDefaults.AuthenticationScheme}")]
Run Code Online (Sandbox Code Playgroud)
编辑:我做了进一步的研究并得出以下结论:不可能使用两个Schemes Or-Like授权方法,但是你可以使用两个公共方法来调用这样的私有方法:
//private method
private IActionResult GetThingPrivate()
{
//your Code here
}
//Jwt-Method
[Authorize(AuthenticationSchemes = $"{JwtBearerDefaults.AuthenticationScheme}")]
[HttpGet("bearer")]
public IActionResult GetByBearer()
{
return GetThingsPrivate();
}
//Cookie-Method
[Authorize(AuthenticationSchemes = $"{CookieAuthenticationDefaults.AuthenticationScheme}")]
[HttpGet("cookie")]
public IActionResult GetByCookie()
{
return GetThingsPrivate();
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*ens 10
经过数小时的研究和头疼,这就是在 ASP.NET Core 2.2 -> ASP.NET 5.0 中对我有用的方法:
您不需要在每个控制器操作上指定方案,并且适用于两者。【授权】就够了。
services.AddAuthentication( config =>
{
config.DefaultScheme = "smart";
} )
.AddPolicyScheme( "smart", "Bearer or Jwt", options =>
{
options.ForwardDefaultSelector = context =>
{
var bearerAuth = context.Request.Headers["Authorization"].FirstOrDefault()?.StartsWith( "Bearer " ) ?? false;
// You could also check for the actual path here if that's your requirement:
// eg: if (context.HttpContext.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCulture))
if ( bearerAuth )
return JwtBearerDefaults.AuthenticationScheme;
else
return CookieAuthenticationDefaults.AuthenticationScheme;
};
} )
.AddCookie( CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = new PathString( "/Account/Login" );
options.AccessDeniedPath = new PathString( "/Account/Login" );
options.LogoutPath = new PathString( "/Account/Logout" );
options.Cookie.Name = "CustomerPortal.Identity";
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromDays( 1 ); //Account.Login overrides this default value
} )
.AddJwtBearer( JwtBearerDefaults.AuthenticationScheme, options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey( key ),
ValidateIssuer = false,
ValidateAudience = false
};
} );
services.AddAuthorization( options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder( CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme )
.RequireAuthenticatedUser()
.Build();
} );
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7761 次 |
最近记录: |