【问题标题】:Angular 5 HTTP Client has "Authorization" missing from the Response headerAngular 5 HTTP 客户端的响应标头中缺少“授权”
【发布时间】:2018-07-24 10:32:32
【问题描述】:

我正在使用 JWT(JSON Web 令牌)作为将人们登录到系统的一部分。执行此操作的代码如下:

this.http.post(url, JSON.stringify({ username: username, password: password }), { observe: 'response' })
      .subscribe((response: HttpResponse<any>) => {

usernamepassword发送到服务器时,Response对象的Header中包含加密的授权。

作为标题的一部分包含一个Authorization 条目和一个Pragma 条目。 Authorization 正确定义了令牌(并且可以正常工作)。 Pragma 也定义为no-cache

来自 Chrome 中的网络标签:

但是在运行代码来处理响应标头时,Authorization 标头不存在。

 adminLogin(username, password) {
    let url = `${this._apiRoot}/login`;
    let tokenResp = {};

    this.http.post(url, JSON.stringify({ username: username, password: password }), { observe: 'response' })
      .subscribe((response: HttpResponse<any>) => {

        console.log(" ---- begin response ----");
        console.log( response );
        console.log(" ---- end response ----");

        let token = response.headers.get("Authorization");

        console.log(" ---- begin token ----");
        console.log ( token );
        console.log(" ---- end token ----");

        let pragma = response.headers.get("pragma");

        console.log(" ---- begin pragma ----");
        console.log ( pragma );
        console.log(" ---- end pragma ----");

执行代码的结果:

从执行的代码中可以看出,试图找到Authorization 返回null,而Pragma 得到no-cache。怎么回事?

更新

感谢大家提供的信息。

我在这里关注了信息: https://github.com/angular/angular/issues/13554

并对java代码进行了修改:

@Override
    protected void successfulAuthentication(HttpServletRequest req,
            HttpServletResponse res, FilterChain chain, Authentication auth)
            throws IOException, ServletException {
        String username = ((User) auth.getPrincipal()).getUsername();
        ApplicationUser user = applicationUserRepository
                .findByUsername(username);

        String token = Jwts
                .builder()
                .setSubject(((User) auth.getPrincipal()).getUsername())
                .claim("id", user.getId())

            [... snip ...]

            res.addHeader("Access-Control-Expose-Headers", "Authorization");
            res.addHeader(SecurityConstants.HEADER_STRING,SecurityConstants.TOKEN_PREFIX + token);

    }

再次感谢!

【问题讨论】:

  • 该header不允许暴露给代码,需要设置Access-Control-Expose-Headers;参见例如stackoverflow.com/a/43010215/3001761
  • github.com/angular/angular/issues/20554。您必须允许使用 Access-Control-Expose-Headers 的标题
  • 另外请注意,您不必自己 JSON.stringify 正文,您可以使用对象速记符号来编写例如{ username, password }。另一个相关Q:stackoverflow.com/q/42306684/3001761
  • 您可以发布您的“更新”作为答案。让其他人更容易看到它
  • 假设我不想暴露标题。如果令牌出现在 Authorization 标头中,我应该如何将令牌存储在客户端或发送经过身份验证的请求?

标签: angular http jwt


【解决方案1】:
const options = {
        headers: new HttpHeaders({
            'Content-Type': 'application/json',
            Authorization: 'Bearer ' + token
        })
    };
    const requestPayload = ({
        user_type: userType
    });
    return this.http.post<UserModel>(`${API_BASE_URL}/user/${uid}`, JSON.stringify(requestPayload), options);

如果您不想使用拦截器方法,上述方法应该可以正常工作,但在这种情况下,post 方法需要 3 个参数才能工作:endpoiontURL |请求正文 |标头选项

【讨论】:

  • 这并没有回答有关如何从 http 响应中读取令牌的问题
【解决方案2】:

为了解决这个问题,我们需要从后端公开所需的标头,并使用和编写自定义的HttpInterceptor

NodeJs API 示例:从后端公开 authorization 标头

res.setHeader('Access-Control-Expose-Headers', 'authorization'); 
res.setHeader('authorization', 'foo-bar');

角度拦截器示例

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
    return next.handle(request).pipe(
      tap(response => {
        if (response.headers) {
          console.log('Header keys', response.headers.keys());
          console.log('Authorization: ', response.headers.get('authorization'));
        }
      }),
    );
  }
}

最后,我们将拦截器添加到我们的模块提供程序中

import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpInterceptorService } from './http-interceptor.service';

@NgModule({
  ...
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true },
  ],
})
export class AppModule {}

sample coderepos can 有助于了解更多关于 Angular HttpInterceptor 的信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-15
    • 2016-03-08
    • 2018-12-31
    • 2013-02-13
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    相关资源
    最近更新 更多