如何在角度中使用keycloak访问令牌

时间:2018-03-23 17:54:27

标签: angular keycloak

我已经在我的Spring启动应用程序中集成了keycloak适配器,如文档中所述。工作流程正在运行。 最初,我在属性中使用会话令牌存储,但我想摆脱它并且是无状态的。所以,我将选项更改为cookie令牌存储。

我可以看到我的Spring Boot应用程序确实在KEYCLOAK_ADAPTER_STATE cookie(screenshot)中发送了keycloak访问令牌。正如所料,它被标记为HTTP cookie。

但是,即使我在查询中打开withCredentials选项,当我查询后端时,进一步的角度http请求也不会发送该cookie。

let options : RequestOptions = new RequestOptions();
options.withCredentials = true;
this.http.get('myservice', options)

如何在无状态的http调用中使用该令牌?

非常感谢!

4 个答案:

答案 0 :(得分:0)

使用Interceptors

  

HTTP拦截是@ angular / common / http的主要功能。同   拦截,你声明检查和转换HTTP的拦截器   从您的应用程序到服务器的请求。同样的拦截器   也可以检查并转换服务器的响应   回到应用程序。多个拦截器形成一个   请求/响应处理程序的前后链

     

从'../ auth.service'导入{AuthService};

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private auth: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // Get the auth token from the service.
    const authToken = this.auth.getAuthorizationToken();

    // Clone the request and replace the original headers with
    // cloned headers, updated with the authorization.
    const authReq = req.clone({
      headers: req.headers.set('Authorization', authToken)
    });

    // send cloned request with header to the next handler.
    return next.handle(authReq);
  }
}

...

  

我认为您应该将options.withCredentials = true;设置为任何请求

import { Injectable } from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse, HttpErrorResponse} from '@angular/common/http';
import {Router} from '@angular/router';

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/do';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private router: Router) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    req = req.clone({
      withCredentials: true
    });

    return next
      .handle(req)
      .do(event => {
        if (event instanceof HttpResponse) {}
      }, (error: any) => {
        if (error instanceof HttpErrorResponse) {
          if (error.status === 401) {
            this.router.navigate(['/login']);
          }
        }
      });
  }
}

答案 1 :(得分:0)

我发现了问题。到达我的页面的初始请求URL是“/ app / mymodule”,因此keycloak HTTP令牌绑定到/ app路径;但我查询后端的JS http请求是“/ services / myservice”,因此浏览器不会发送cookie,因为根路径不匹配。我在/ app / services下移动了我的服务,现在令牌按预期发送,并经过适当验证:)。

答案 2 :(得分:0)

尝试使用https://www.npmjs.com/package/keycloak-angular

有了出色的文档,它使该过程变得更加容易。

它使用npm软件包中内置的拦截器,因此您不必担心将令牌附加到每个请求。

答案 3 :(得分:0)

默认情况下,如angular-keycloak documentation HttpClient拦截器中所述,将为以下格式添加Authorization标头:从应用程序到服务器的所有HTTP请求的Authorization:Bearer TOKEN

您可以配置要从HTTPClient拦截器配置中添加带有密钥斗篷令牌的HTTP授权标头中要排除的请求URL。

可以在app-init.ts(请参阅angular-keycloak文档)中的keycloak初始化程序函数中配置HttpClient拦截器;

import { KeycloakService } from 'keycloak-angular';

export function initializer(keycloak: KeycloakService): () => Promise<any> {
    return (): Promise<any> => keycloak.init({
        config: {
            url: 'http://localhost:8080/auth',
            realm: 'your-realm',
            clientId: 'client-id'
        },
        initOptions: {
            onLoad: 'login-required',
            checkLoginIframe: false
        },
        enableBearerInterceptor: true,
        bearerPrefix: 'Bearer',
        bearerExcludedUrls: [
            '/assets',
            '/clients/public']
    });
}