为什么在上下文之后调用 webapi 控制器的方法。Rejected() 已在 ValidateIdentity(OAuthValidateIdentityContext context) 中调用



>在VS2013中从模板创建的webapi应用程序中,我在Startup.Auth中添加了自定义OAuthBearerAuthenticationProvider类.cs文件:

public class CustomBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
{
    public override Task ValidateIdentity(OAuthValidateIdentityContext context)
    {
        UserManager<ApplicationUser> userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
        var user = userManager.FindById(context.Ticket.Identity.GetUserId());
        var claims = context.Ticket.Identity.Claims;
        if (claims.FirstOrDefault(claim => claim.Type == "AspNet.Identity.SecurityStamp") == null 
            || claims.Any(claim => claim.Type == "AspNet.Identity.SecurityStamp" 
                && !claim.Value.Equals(user.SecurityStamp)))
        {
            context.Rejected();
        }
        return Task.FromResult<object>(null);
    }
}

我还添加了变量:

public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

在 ConfigureAuth(IAppBuilder app) 方法中,我添加了以下代码行来使用自定义 OAuthBearerAuthenticationProvider 类:

OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
OAuthBearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
OAuthBearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
OAuthBearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
OAuthBearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
OAuthBearerOptions.Description = OAuthOptions.Description;
OAuthBearerOptions.Provider = new CustomBearerAuthenticationProvider();
OAuthBearerOptions.SystemClock = OAuthOptions.SystemClock;
app.UseOAuthBearerAuthentication(OAuthBearerOptions);

我所做的所有这些更改都是为了实现我自己的持有者令牌验证的自定义逻辑。由于某种原因,在VS 2013中从模板创建的Webapi应用程序中未实现安全标记验证。我认为这应该默认完成。

为了验证SecurityStamp验证概念,我更改了数据库中的SecurityStamp,然后使用旧的持有者令牌从客户端调用了一些webapi方法,即包含旧的SecurityStamp声明。请注意,我的 webapi 控制器带有 [授权] 属性注释。之后,ValidateIdentity(OAuthValidateIdentityContext context)方法被调用和上下文。拒绝()行已被执行,我希望之后不应该调用webapi方法,并且应该将401未经授权的响应发送回客户端。

但这一切都没有发生。Webapi 方法确实被调用,客户端确实成功地从服务器获取敏感数据,而不应该,因为客户端发送到服务器进行身份验证和授权的旧持有者令牌在密码更改后一定无效。

我想如果上下文。拒绝() 已在 ValidateIdentity 方法中调用任何 [授权] 修饰的 webapi 方法,并且客户端应收到类似 401 未经授权的响应。

我是不是误解了整件事?如果我是,请问有人可以解释一下它是如何工作的?为什么在上下文之后。拒绝() 已被调用 [授权] 注释控制器的 webapi 方法被调用并成功返回敏感数据?为什么没有发送 401 未授权响应?当SecurityStamp声明与当前数据库中的声明不同时,如何实现将401未经授权的响应发送回客户端的目标?

最后,

我能够找到事物如何工作的解释。这是孙宏业对他回答堆积问题的评论:你如何拒绝武士刀持有者令牌的身份

我在这里引用它:"UseOAuthBearerTokens会将Bearer身份验证中间件和授权服务器中间件注册到管道中。如果调用这两种方法,则将注册两个承载身份验证中间件。您需要调用UseOAuthAuthorizationServer来注册授权服务器。

所以我替换了这行代码:

app.UseOAuthBearerTokens(OAuthOptions);

对此:

app.UseOAuthAuthorizationServer(OAuthOptions);

事情开始按预期进行。 即未调用 [授权] 注释控制器的 webapi 方法,并且在上下文之后发回 401 未授权响应。已调用 Rejected()。

最新更新