Web Api OWIN - 如何在每个请求上验证令牌

Posted

技术标签:

【中文标题】Web Api OWIN - 如何在每个请求上验证令牌【英文标题】:Web Api OWIN - How to validate token on each request 【发布时间】:2019-01-03 07:49:16 【问题描述】:

我有两个应用程序

    基于 ASP.NET MVC 构建的客户端应用程序 基于 Web API + OWIN 构建的身份验证服务器

已计划如下身份验证

    对于用户登录,客户端应用程序将使用登录凭据向身份验证服务器发出请求。 身份验证服务器将生成一个令牌并将其发送回客户端应用程序。 客户端应用程序将该令牌存储在本地存储中。 对于每个后续请求,客户端应用程序将附加令牌,该令牌保存在请求标头中的本地存储中。

现在,在 CLEINT 应用程序的服务器端,我需要验证每个请求附带的令牌未经过调和。

    请建议我如何在每个请求中验证令牌,因为我不知道 OWIN 用于生成令牌的密钥。 编写代码来验证客户端应用程序上的令牌是正确的,或者它应该在身份验证服务器上。 我打算转移所有用户管理代码,例如注册用户,将密码更改为身份验证服务器,以便我们可以将其重新用于不同的客户端应用程序 - 这是正确的设计实践吗?

到目前为止,我已经编写了以下代码来创建 POC。

==========================OWIN配置========

    [assembly: OwinStartup(typeof(WebApi.App_Start.Startup))]
    namespace WebApi.App_Start
    
        public class Startup
        
            public void Configuration(IAppBuilder app)
            
                HttpConfiguration config = new HttpConfiguration();

                ConfigureOAuth(app);

                WebApiConfig.Register(config);
                app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
                app.UseWebApi(config);
            

            public void ConfigureOAuth(IAppBuilder app)
            
                OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
                
                    AllowInsecureHttp = false,
                    TokenEndpointPath = new PathString("/token"),
                    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                    Provider = new SimpleAuthorizationServerProvider(),

         ;

         // Token Generation

                app.UseOAuthAuthorizationServer(OAuthServerOptions);
                app.UseOAuthBearerAuthentication(new 
 OAuthBearerAuthenticationOptions());

            
        
    

==============================oAuth Provided========================

 public class SimpleAuthorizationServerProvider: OAuthAuthorizationServerProvider
    
        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        
            context.Validated(); 
        

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        


            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[]  "*" );

            using (AuthRepository _repo = new AuthRepository())
            
                IdentityUser user =  _repo.FindUser(context.UserName, context.Password);

                if (user == null)
                
                    context.SetError("invalid_grant", "The user name or password is incorrect.");
                    return;
                
            

            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
            identity.AddClaim(new Claim("sub", context.UserName));
            identity.AddClaim(new Claim("role", "user"));

            context.Validated(identity);

        
    

请帮忙,

谢谢,

@保罗

【问题讨论】:

不要将本地存储用于身份验证令牌,这不安全。最好用饼干。 owasp.org/index.php/html5_Security_Cheat_Sheet#Local_Storage 【参考方案1】:

请建议我如何在每个请求中验证令牌,因为我没有 知道 OWIN 用来生成令牌的密钥。

如果您已将 app.UseOAuthBearerAuthentication() 添加到 owin 管道,您当前的设置将通过在每个请求中为您传递的不记名令牌对用户进行身份验证。 然后可以通过HttpContext.Current.User 找到当前用户。

使用Authorize 属性来决定哪些用户在某些端点上被授权。 这是一个允许具有“user”角色的用户访问的示例

[Authorize(Roles="user")]
public class ValuesController : ApiController


编写代码来验证客户端应用程序上的令牌是正确的,或者应该 在身份验证服务器上。

,您不会在客户端验证令牌,如果您的用户凭据错误,您根本不会获得令牌。这就是你需要知道的。 还有,为什么要在客户端验证令牌?

我打算转移所有用户管理代码,如注册用户, 将密码更改为身份验证服务器,以便我们可以重新使用它 不同的客户端应用程序 - 这是正确的设计实践吗?

重复使用令牌提供程序很常见。为什么要为每个应用程序发明***?构建一个伟大的,或使用第三方,并在您的应用程序中重用它。

【讨论】:

感谢您的回复@Marcus。 是的 app.UseOAuthBearerAuthentication() 已添加。我已经看到如果我尝试使用无效令牌从同一授权服务器(localhost:58386)访问任何受限资源,服务器在内部验证令牌并且不允许访问该方法。但是我的客户端应用程序位于不同的域中(localhost:57543)。我想使用相同的授权服务器(localhost:58386)对我的客户端应用程序(localhost:57543)中定义的所有 [Authorized] 方法进行身份验证和授权 我找不到需要在客户端应用程序中执行的配置来告诉客户端应用程序使用授权服务器(Web api 应用程序)进行身份验证和授权。请帮忙。 @paulsim 您需要启用客户端应用程序来解码和读取从授权 api 生成的令牌。两个应用程序需要使用相同的机器密钥。这是一个很棒的博客,它逐步描述了这一点bitoftech.net/2014/09/24/…。 Np,如果这个答案有任何帮助,请投票/接受。【参考方案2】:

使用JSON Web Tokens (JWT) 和声明身份,而不是需要跟踪已发行令牌的随机令牌。

JWT 就像是由受信任的权威机构签发的护照。护照已签名/盖章,您可以验证它是由这个受信任的机构签发的,并且没有被篡改。这意味着,可以验证令牌中存在的访问权限声明的完整性,而无需在任何地方保留状态。信任应用程序和授权机构之间需要进行的唯一通信是初始(安全)下载授权机构的公钥(用于签署令牌)。

还建议您使用标准声明架构,例如 OpenID Connect (http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)

一本关于该主题的好书,它帮助我了解所有这些概念,可以在这里找到:A Guide to Claims-Based Identity and Access Control。

【讨论】:

【参考方案3】:

验证令牌未被篡改的一种方法是使用非对称密钥对对其进行签名,Identity Server 使用这种方法,如 here 所示。

在您的情况下,如果您正在滚动自己的身份验证,则需要自己实现此功能,并可能在自定义中间件中检查每个请求是否令牌有效。

【讨论】:

【参考方案4】:

如果您在localStorage 中的createsendbacksave 以及关于JWT 令牌的所有内容都是正确的,那么您必须知道.Net 中有很多方法可以控制每个请求.

服务器端控制:

    1234563

    如果你使用Asp.net MVC,你可以在MVC中使用ActionFilter(Asp.Net-Core也有更高级的ActionFilter),每个请求都会通过,你可以检查每个thisng abount请求,更多信息请查看:This。

客户端配置:

    在您从服务器端登录后提供 Token 之后,您必须将数据保存在 localstorage 中,以便您的浏览器根据请求检查该数据,它们的优势是 Expireation 和每个喜欢这个问题的 token 保存在localstorage 中,您和浏览器可以使用它来查看更多信息:This。

祝你好运。

【讨论】:

至于#2,你也可以使用利用OWIN的中间件。

以上是关于Web Api OWIN - 如何在每个请求上验证令牌的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Web API 的 Owin 身份验证的 Provider 类中获取 Windows 登录?

Web API 2 OWIN Bearer Token cookie的用途?

具有 OWIN 自主机和 Windows 身份验证的 Web Api

尝试在 ASP.net Web API 中发生授权之前使用 OWIN 注入授权标头

具有混合身份验证 JWT 和 SAML 的 ASP.NET Web API 2.2 OWIN

Owin Web API Bearer Token 直通