如何使用 jwt 在 Angular 6 和 web api 中刷新令牌?
Posted
技术标签:
【中文标题】如何使用 jwt 在 Angular 6 和 web api 中刷新令牌?【英文标题】:How to refresh token in Angular 6 and web api using jwt? 【发布时间】:2019-08-16 17:15:44 【问题描述】:我在我的 Angular 6 项目中使用了 jwt 令牌和 Web API。 我可以通过生成 token 登录到我的会话,但是当它过期时让我们说 10 分钟后。我想显示一个弹出窗口,它会说,您的会话已过期,请单击下面刷新您的会话。这将生成一个新令牌,可用于访问我的门户。
我尝试了以下代码,使用下面的一些链接
https://steemit.com/utopian-io/@babelek/how-to-manage-with-refresh-token-in-asp-net-core-2-0-web-api
http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/
Refresh token (JWT) in interceptor Angular 6
在我的 angular 6. 文件中的身份验证拦截器文件中,我添加了如下代码
intercept(req: HttpRequest<any>, next: HttpHandler)
const token = sessionStorage.getItem('token');
const authReq = req.clone( setHeaders: Authorization: 'bearer ' +
token );
return next.handle(authReq).do((event: HttpEvent<any>) =>
if (event instanceof HttpResponse)
// if the token is valid
, (err: any) =>
if (err instanceof HttpErrorResponse)
if (err.status === 401)
const refreshToken =
sessionStorage.getItem('refreshToken');
this.loginService.refreshToken([refreshToken]).subscribe((res: any) =>
const tokenInfo =
this.loginService.getDecodedAccessToken(res.access_token);
const loggedUser = tokenInfo.userName;
this.loginService.setToken(res.access_token,
loggedUser, res.refresh_token);
sessionStorage.setItem('userName', loggedUser);
, error =>
);
this.router.navigateByUrl('/login');
this.authService.collectFailedRequest(authReq);
);
在我的登录服务文件中,我添加了以下代码
public getToken(parameter: string[]): Observable<any>
const data = new HttpParams()
.set('username', parameter[0])
.set('password', parameter[1])
.set('grant_type', 'password');
const url = this.API_URL + '/api/confirm_login';
return this._httpClient.post(url, data.toString()).pipe(
map(x => x),
catchError((error: any) =>
let errorMessage: any;
if (error.error && error.error.error_description)
errorMessage = error.error.error_description;
throw errorMessage;
)
);
public refreshToken(parameter: string[]): Observable<any>
const data = new HttpParams()
.set('refresh_token', parameter[0])
.set('grant_type', 'refresh_token');
const url = this.API_URL + '/api/refresh_token';
return this._httpClient.post(url, data.toString()).pipe(map(x => x),
catchError((error: any) =>
let errorMessage: any;
if (error.error && error.error.error_description)
errorMessage = error.error.error_description;
throw errorMessage;
)
);
public setToken(token: any, getLoggedUser: any, refresh_token: any)
sessionStorage.setItem('token', token);
sessionStorage.setItem('userName', getLoggedUser);
sessionStorage.setItem('refreshToken', refresh_token);
getDecodedAccessToken(token: string): any
try
return jwt_decode(token);
catch (Error)
return null;
在我的 authservice 文件中我添加了
authenticated(): boolean
const token = sessionStorage.getItem('token');
if (!token)
return null;
return !this.jwtHelper.isTokenExpired(token);
在我的 startup.cs 文件中我添加了
public void ConfigureOAuth(IAppBuilder app)
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
OAuthAuthorizationServerOptions OAuthServerOptions = new
OAuthAuthorizationServerOptions()
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/api/confirm_login"),
AccessTokenExpireTimeSpan = TimeSpan.FromMilliseconds(30000),
Provider = new ldAuthorizationServerProvider(),
AccessTokenFormat = new
ldTokenFormat(ConfigurationManager.AppSettings["as:AngularHostURL"]),
RefreshTokenProvider = new RefreshTokenProvider(),
AuthorizeEndpointPath = new PathString("/api/refresh_token"),
;
app.UseOAuthAuthorizationServer(OAuthServerOptions);
这是我的刷新令牌提供者
public class RefreshTokenProvider : IAuthenticationTokenProvider
private static ConcurrentDictionary<string, AuthenticationTicket>
_refreshTokens = new ConcurrentDictionary<string, AuthenticationTicket>();
public async Task CreateAsync(AuthenticationTokenCreateContext
context)
var guid = Guid.NewGuid().ToString();
// copy all properties and set the desired lifetime of refresh
token
var refreshTokenProperties = new
AuthenticationProperties(context.Ticket.Properties.Dictionary)
IssuedUtc = context.Ticket.Properties.IssuedUtc,
ExpiresUtc =
DateTime.UtcNow.AddMilliseconds(30000)//DateTime.UtcNow.AddYears(1)
;
var refreshTokenTicket = new
AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties);
_refreshTokens.TryAdd(guid, refreshTokenTicket);
// consider storing only the hash of the handle
context.SetToken(guid);
public void Create(AuthenticationTokenCreateContext context)
throw new NotImplementedException();
public void Receive(AuthenticationTokenReceiveContext context)
throw new NotImplementedException();
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
Guid token;
if (Guid.TryParse(context.Token, out token))
AuthenticationTicket ticket;
if (_refreshTokens.TryRemove(token, out ticket))
context.SetTicket(ticket);
这里我的代码没有到达 GrantRefreshToken 方法。我不确定我错过了什么。
感谢任何帮助
【问题讨论】:
【参考方案1】:在示例中,我有用于登录和刷新令牌的共享令牌端点是 /Token。除了令牌端点外,我的代码与您完全相同。当我向它发出邮递员请求时,我点击了 GrantRefreshToken 代码..
或者,这个的角度代码是
refreshToken(): Observable<any>
let headers = new Headers( 'Content-type': 'application/x-www-form-urlencoded' );
headers.append('Content-Type', 'application/json');
headers.append('No-Auth', 'True');
var refreshToken = <the guid in the refresh_token local storage>
let body = 'grant_type=refresh_token&refresh_token=' + refreshToken;
return this._http.post(<some url> + '/Token', body, headers:headers);
【讨论】:
能否就 Angular/Azure AD 与您联系?我看到你已经做了很多。如果是这样,请在我的个人资料中发送电子邮件给我。谢谢!以上是关于如何使用 jwt 在 Angular 6 和 web api 中刷新令牌?的主要内容,如果未能解决你的问题,请参考以下文章
将 JWT 存储在基于会话的 cookie Angular 6 中