如何在 keycloak 中设置 CORS 配置以允许 ajax 请求?
How to setup the CORS configuration in keycloak to allow an ajax request?
我正在尝试使用 keycloak 作为身份验证服务器。
我尝试通过 ajax 请求获取令牌。由于 CORS,它在 curl 中工作正常,但在我的 angular 中无效。
我已将客户端设置为 Direct access grant enable 为 true,并且已将 * 添加到 Web Origin。
fetch("http://localhost:8080/auth/realms/master/protocol/openid-connect/token", {
body: "grant_type=password&client_id=admin-cli&username=adrien&password=adrien&undefined=",
headers: {
Accept: "application/json, text/plain, */*,application/x-www-form-urlencoded",
"Access-Control-Allow-Headers": "Origin, Content-Type, Authorization, Content-Length, X-Requested-With",
"Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,OPTIONS",
"Access-Control-Allow-Origin": "*",
"Cache-Control": "no-cache",
"Content-Type": "application/x-www-form-urlencoded",
Dnt: "1",
"Postman-Token": "cfd33776-882d-4850-b2e7-d66629da3826"
},
method: "POST"
})
你知道我错过了什么吗?
提前致谢。
我认为您试图以错误的方式使用它。 angular 有一个插件,我认为你应该使用它。所以这里是 clifnotes。安装插件:
npm i keycloak-angular
然后初始化keycloack:
import {KeycloakService} from 'keycloak-angular';
export function initializer(keycloak: KeycloakService): () => Promise<any> {
return (): Promise<any> => {
return new Promise(async (resolve, reject) => {
try {
await keycloak.init({
config: {
url: 'http://localhost:8080/auth',
realm: 'MySecureRealm',
clientId: 'myAngularApplication'
},
initOptions: {
onLoad: 'login-required',
checkLoginIframe: false,
responseMode: 'fragment',
flow: 'standard'
}
});
resolve();
} catch (error) {
reject(error);
}
});
};
}
然后在 app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import {APP_INITIALIZER, NgModule} from '@angular/core';
import { AppComponent } from './app.component';
import {KeycloakService} from 'keycloak-angular';
import {initializer} from '../environments/environment';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import {TokenInterceptor} from './token-interceptor';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
KeycloakService,
{
provide: APP_INITIALIZER,
useFactory: initializer,
multi: true,
deps: [KeycloakService]
},
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
],
bootstrap: [AppComponent]
})
export class AppModule { }
您还需要这个 TokenInterceptor:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/observable/fromPromise';
import { KeycloakService, KeycloakAuthGuard, KeycloakAngularModule } from 'keycloak-angular';
import {HttpHeaders} from '@angular/common/http/src/headers';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(protected keycloak: KeycloakService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return Observable
.fromPromise(this.keycloak.getToken())
.mergeMap(
token => {
console.log('adding heder to request');
console.log(token);
const headers: HttpHeaders = req.headers;
const hedersWithAuthorization: HttpHeaders = headers.append('Authorization', 'bearer ' + token);
const requestWithAuthorizationHeader = req.clone({ headers: hedersWithAuthorization });
return next.handle(requestWithAuthorizationHeader);
}
);
}
}
应该就可以了。当您进入应用程序但未登录时,您将被重定向到 keycloak 登录屏幕并返回到您的应用程序。并且所有传出请求都将添加身份验证 header。如果您有任何问题,请告诉我。我非常了解这项技术。
我正在尝试使用 keycloak 作为身份验证服务器。 我尝试通过 ajax 请求获取令牌。由于 CORS,它在 curl 中工作正常,但在我的 angular 中无效。 我已将客户端设置为 Direct access grant enable 为 true,并且已将 * 添加到 Web Origin。
fetch("http://localhost:8080/auth/realms/master/protocol/openid-connect/token", {
body: "grant_type=password&client_id=admin-cli&username=adrien&password=adrien&undefined=",
headers: {
Accept: "application/json, text/plain, */*,application/x-www-form-urlencoded",
"Access-Control-Allow-Headers": "Origin, Content-Type, Authorization, Content-Length, X-Requested-With",
"Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,OPTIONS",
"Access-Control-Allow-Origin": "*",
"Cache-Control": "no-cache",
"Content-Type": "application/x-www-form-urlencoded",
Dnt: "1",
"Postman-Token": "cfd33776-882d-4850-b2e7-d66629da3826"
},
method: "POST"
})
你知道我错过了什么吗?
提前致谢。
我认为您试图以错误的方式使用它。 angular 有一个插件,我认为你应该使用它。所以这里是 clifnotes。安装插件:
npm i keycloak-angular
然后初始化keycloack:
import {KeycloakService} from 'keycloak-angular';
export function initializer(keycloak: KeycloakService): () => Promise<any> {
return (): Promise<any> => {
return new Promise(async (resolve, reject) => {
try {
await keycloak.init({
config: {
url: 'http://localhost:8080/auth',
realm: 'MySecureRealm',
clientId: 'myAngularApplication'
},
initOptions: {
onLoad: 'login-required',
checkLoginIframe: false,
responseMode: 'fragment',
flow: 'standard'
}
});
resolve();
} catch (error) {
reject(error);
}
});
};
}
然后在 app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import {APP_INITIALIZER, NgModule} from '@angular/core';
import { AppComponent } from './app.component';
import {KeycloakService} from 'keycloak-angular';
import {initializer} from '../environments/environment';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import {TokenInterceptor} from './token-interceptor';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
KeycloakService,
{
provide: APP_INITIALIZER,
useFactory: initializer,
multi: true,
deps: [KeycloakService]
},
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
],
bootstrap: [AppComponent]
})
export class AppModule { }
您还需要这个 TokenInterceptor:
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/observable/fromPromise';
import { KeycloakService, KeycloakAuthGuard, KeycloakAngularModule } from 'keycloak-angular';
import {HttpHeaders} from '@angular/common/http/src/headers';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(protected keycloak: KeycloakService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return Observable
.fromPromise(this.keycloak.getToken())
.mergeMap(
token => {
console.log('adding heder to request');
console.log(token);
const headers: HttpHeaders = req.headers;
const hedersWithAuthorization: HttpHeaders = headers.append('Authorization', 'bearer ' + token);
const requestWithAuthorizationHeader = req.clone({ headers: hedersWithAuthorization });
return next.handle(requestWithAuthorizationHeader);
}
);
}
}
应该就可以了。当您进入应用程序但未登录时,您将被重定向到 keycloak 登录屏幕并返回到您的应用程序。并且所有传出请求都将添加身份验证 header。如果您有任何问题,请告诉我。我非常了解这项技术。