我们知道,为了安全起见,AccessToken的有效时间一般是比较短的(如30分钟)。在AccessToken超出有效期之后,它就不能再用于访问资源,必须重新获得。但如果每30分钟,就要让用户登录一次,那必定会让用户感到厌烦。于是就产生了RefreshToken这个概念。
在获得AccessToken的同时,得到RefreshToken。在AccessToken过期之后,不需要请求用户重新输入账号,直接用RefreshToken获得新的AccessToken。
下面,我们在授权码模式下,加入RefreshToken的实现。
首先,我们需要一个RefreshToken提供类。其跟授权码提供类非常像,具体测试代码如下:
public class RefreshTokenProvider : AuthenticationTokenProvider
{
private static Dictionary<string, string> tokens = new Dictionary<string, string>();
public override void Create(AuthenticationTokenCreateContext context)
{
context.Ticket.Properties.IssuedUtc = DateTime.UtcNow;
context.Ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddDays(60);
context.SetToken(Guid.NewGuid().ToString("n"));
tokens.Add(context.Token, context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
string token = context.Token;
if (tokens.ContainsKey(token))
{
string value = tokens[token];
tokens.Remove(token);
context.DeserializeTicket(value);
}
}
}
然后,我们需要修改Startup类中的服务器配置,改为:
AllowInsecureHttp = true,//允许http而非https访问
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,//激活授权码模式
TokenEndpointPath = new PathString("/token"),//访问host/token获取AccessToken
AuthorizeEndpointPath = new PathString("/auth"),//访问host/auth获取授权码
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),//AccessToken在30分钟后过期
Provider = new AuthorizationServerProvider(),//AccessToken的提供类
AuthorizationCodeProvider = new AuthorizationCodeProvider(),//授权码的提供类
RefreshTokenProvider = new RefreshTokenProvider()//RefreshToken的提供类
其实就是增加了RefreshTokenProvider这一项配置。
在AuthorizationServerProvider类中,ValidateTokenRequest实现Token请求的验证,需要改成如下所示:
public override async Task ValidateTokenRequest(OAuthValidateTokenRequestContext context)
{
if (context.TokenRequest.IsAuthorizationCodeGrantType)
{
context.Validated();
}
else if (context.TokenRequest.IsRefreshTokenGrantType)
{
context.Validated();
}
else
{
context.Rejected();
}
}
这样的话,就同时支持了授权码模式和RefreshToken模式了。
到此为止,对RefreshToken支持的代码已经完成。
RefreshToken请求参数中要求如下:
(1)grant_type,为refresh_token。
(2)refresh_token,为获取AccessToken时得到的RefreshToken。
(3)client_id,客户端ID。
我们使用Postman进行测试。先获取授权码:
使用授权码获取AccessToken和RefreshToken:
使用RefreshToken更新AccessToken: