2016-09-26 74 views
4

我有一个允许匿名用户的ASP.NET Core MVC应用程序。这个程序是调用由身份服务器4.我已经创建了Identity Server的客户端描述MVC应用程序(客户端)的保护,给予其访问API范围这样的ASP.NET Web API:使用客户端证书持久化令牌的最佳实践流程

new Client 
{ 
    ClientId = "my-mvc-client-app", 
    AllowedGrantTypes = GrantTypes.ClientCredentials, 

    RequireConsent = false, 
    ClientSecrets = new List<Secret> { new Secret("this-is-my-secret".Sha256()) }, 
    AllowedScopes = new List<string> 
    { 
     StandardScopes.OpenId.Name, 
     StandardScopes.Profile.Name, 
     StandardScopes.OfflineAccess.Name, 
     "my-protected-api" 
    }, 
    RedirectUris = new List<string> 
    { 
     "http://localhost:5009/signin-oidc", 
    } 
} 

在我的MVC应用程序,我使用TokenClient获得令牌发出请求,以这样的受保护的API时,我可以使用:

var disco = await DiscoveryClient.GetAsync("http://localhost:5010"); 
var tokenClient = new TokenClient(disco.TokenEndpoint, clientId, clientSecret); 
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("hrmts-test-candidate-api-scope"); 

这工作得很好,但我请求来自Identity Server的新令牌在每个请求上,这可能不是一个好主意。

处理令牌的最佳做法是什么?我如何将它们保存在客户端(MVC应用程序)上,以及如何处理刷新令牌以确保客户端在必要时获取新令牌?

回答

4

您需要将该客户端包装在某种托管服务(作为单例)中,以便您可以在任何需要的地方使用它。我们有一个令牌组件用于服务器之间的服务器通信,遵循以下流程:

public class ServerTokenComponent 
{ 
    private TokenResponse Token { get; set; } 
    private DateTime ExpiryTime { get; set; } 
    public async Task<TokenResponse> GetToken() 
    { 
     //use token if it exists and is still fresh 
     if (Token != null) 
     { 
      if (ExpiryTime > DateTime.UtcNow) 
      { 
       return Token; 
      } 
     }  

     //else get a new token 
     var client = new TokenClient("myidpauthority.com","theclientId","thesecret") 
     var scopes = "for bar baz"; 

     var tokenResponse = await client.RequestClientCredentialsAsync(scopes); 

     if (tokenResponse.IsError || tokenResponse.IsHttpError) 
     { 
      throw new SecurityTokenException($"Could not retrieve token."); 
     } 

     //set Token to the new token and set the expiry time to the new expiry time 
     Token = tokenResponse; 
     ExpiryTime = DateTime.UtcNow.AddSeconds(Token.ExpiresIn); 

     //return fresh token 
     return Token; 
    } 
} 
+0

我喜欢这种方法,但是,如果这是作为一个单身人士的范围是这个实现线程安全和可重入安全吗? – LugTread

2

IOW - 您需要以某种方式缓存该令牌。当您请求令牌时,您会在回复中得到一个ExpiresIn - 这会告诉您令牌有效的时间。

另一种选择是等到API返回401 - 然后请求新的令牌。

刷新令牌不与客户端凭据流一起使用。