不记名令牌如何在 Web API 2 中存储在服务器端?

Posted

技术标签:

【中文标题】不记名令牌如何在 Web API 2 中存储在服务器端?【英文标题】:How are bearer tokens stored server-side in Web API 2? 【发布时间】:2014-02-01 20:18:13 【问题描述】:

我正在 Web API 2 中设置不记名令牌身份验证,但我不明白不记名令牌是如何(或在何处)存储在服务器端的。以下是相关代码:

启动:

public partial class Startup

    public static OAuthAuthorizationServerOptions OAuthOptions  get; private set; 
    public static Func<UserManager<IdentityUser>> UserManagerFactory  get; set; 
    public static string PublicClientId  get; private set; 

    static Startup()
    
        PublicClientId = "self";
        UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());
        OAuthOptions = new OAuthAuthorizationServerOptions
        
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        ;
    

    public void ConfigureAuth(IAppBuilder app)
    
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseOAuthBearerTokens(OAuthOptions);
    

WebApiConfig:

public class WebApiConfig

    public static void ConfigureWebApi()
    
        Register(GlobalConfiguration.Configuration);
    

    public static void Register(HttpConfiguration http)
    
        AuthUtil.ConfigureWebApiToUseOnlyBearerTokenAuthentication(http);
        http.Routes.MapHttpRoute("ActionApi", "api/controller/action", new action = Actions.Default);
    

AuthUtil:

public class AuthUtil

    public static string Token(string email)
    
        var identity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, email));
        var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        var currentUtc = new SystemClock().UtcNow;
        ticket.Properties.IssuedUtc = currentUtc;
        ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
        var token = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
        return token;
    

    public static void ConfigureWebApiToUseOnlyBearerTokenAuthentication(HttpConfiguration http)
    
        http.SuppressDefaultHostAuthentication();
        http.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
    

登录控制器:

public class LoginController : ApiController

    ...

    public HttpResponseMessage Post([FromBody] LoginJson loginJson)
    
        HttpResponseMessage loginResponse;
        if (/* is valid login */)
        
            var accessToken = AuthUtil.Token(loginJson.email);
            loginResponse = /* HTTP response including accessToken */;
        
        else
        
            loginResponse = /* HTTP response with error */;
        
        return loginResponse;
    

使用上面的代码,我可以登录并将持有者令牌客户端存储在 cookie 中,然后调用标有 [Authorize] 的控制器,它让我进入。

我的问题是:

    不记名令牌在服务器端存储在哪里/如何存储?似乎这是通过 OWIN 调用之一发生的,但我不知道在哪里。

    是否可以将不记名令牌持久保存到数据库服务器端,以便在 Web API 服务器重启后它们可以保留在原位?

    如果对 #2 的回答是否定的,那么即使在 Web API 关闭并重新启动后,客户端是否仍然可以维护其不记名令牌并重新使用它?虽然这在生产环境中可能很少见,但在本地测试中却经常发生。

【问题讨论】:

【参考方案1】:

    它们没有存储在服务器端——它们被发送给客户端,客户端在每次调用时呈现它们。它们已通过验证,因为它们由 owin 主机的保护密钥签名。在 SystemWeb 托管中,该保护密钥是 web.config 中的 machineKey 设置。

    这是不必要的,只要 owin 主机使用的保护密钥在服务器重新启动时不会改变。

    只要令牌有效,客户端就可以持有令牌。

【讨论】:

正如我所说,保护是通过主机的保护,这将是 IIS 中的 machineKey。因此,要使网络农场正常工作,您需要在 web.config 中同步 machineKey。 那么您将获得自动生成的机器密钥。 如何刷新或扩展在任何客户端每次调用服务时生成的令牌?在哪里生成的令牌保持不变,只有到期时间延长了配置的时间? 重新回答1:只是想知道它是否只是一个验证它如何验证到期日期/时间?每个令牌不是不同的吗? @BrockAllen - 使用 Web Api 2,我们试图弄清楚如何从客户端删除令牌。换句话说,我们正在为客户端模拟一个Logout 按钮,目的是删除/使身份验证令牌无效。我们在这方面遇到了一些困难。谢谢。【参考方案2】:

为此,可以使用 CookieAuthenticationOptions 的 SessionStore 属性将令牌持久化到服务器端。我不提倡这样做,但如果你的代币变得过大,它就在那里。

这是一个 IAuthenticationSessionStore,因此您可以实现自己的存储介质。

【讨论】:

【参考方案3】:

对于那些正在寻找如何设置 web.config 的人,这里有一个示例

<system.web>
<machineKey validation="HMACSHA256" validationKey="64-hex"
                 decryption="AES" decryptionKey="another-64-hex"/>
</system.web>

您需要validationKey 和decriptionkey 才能使其工作。

这是生成密钥的方法 https://msdn.microsoft.com/en-us/library/ms998288.aspx

【讨论】:

【参考方案4】:

默认情况下,服务器不存储令牌。只有您的客户端拥有它并通过授权标头将其发送到服务器。

如果您使用 Visual Studio 提供的默认模板,则在 Startup ConfigureAuth 方法中调用以下 IAppBuilder 扩展:app.UseOAuthBearerTokens(OAuthOptions)。

【讨论】:

投反对票。在最初接受的答案后 5 年以上才回答,只回答已发布的问题之一,并且除了接受的答案之外什么都不提供。

以上是关于不记名令牌如何在 Web API 2 中存储在服务器端?的主要内容,如果未能解决你的问题,请参考以下文章

MVC和Web API在不同项目时如何存储不记名令牌

在 ASP.NET Core 2.1 Web 客户端中存储不记名令牌的位置

如何在 MVC 4/Web Api 2 中实现不记名令牌认证

实施 Identity 2.1 + OWIN OAuth JWT 不记名令牌时如何从 Web API 控制器端点进行身份验证

Owin Web API Bearer Token 直通

Web API 安全和身份验证 - 不记名令牌