我正在使用Keycloak和Kong为角度API设置安全配置。
我正在关注下一个教程https://www.jerney.io/secure-apis-kong-keycloak-1/,但是最后我遇到了下一个错误:
CORS策略已阻止从来源“ http://:// localhost:4200”访问“ http://:// localhost:8000 / ops / warehouses”处的XMLHttpRequest:对预检请求的响应未通过访问控制检查:预检请求不允许重定向。
我有一个angular API,可以连接到打字稿中的后端API。所以我想要使用Keycloak前后保护整个API。
我使用Kong作为API网关,使用Konga作为管理界面 孔
Keycloak与Kong的集成通过插件OIDC https://github.com/nokia/kong-oidc
我当前的Keycloak版本是6.0.1,Kong版本是1.2.1和Konga 0.14.3。而且我正在使用Docker将这些元素的每一个部署到容器中。
我的角度应用程序正在使用npm install keycloak-js --save 我遵循下一个配置https://medium.com/@blained3/connecting-keycloak-to-angular-d175c92a0dd3
这是docker compose配置:
// docker-compose.yml
version: '3.4'
networks:
kong_network:
volumes:
kong-datastore:
keycloak-datastore:
services:
kong-db:
image: postgres:9.6
restart: always
volumes:
- kong-datastore:/var/lib/postgresql/data
networks:
- kong_network
ports:
- "15432:5432"
environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_PASSWORD:
healthcheck:
test: ["CMD", "pg_isready", "-U", "kong"]
interval: 5s
timeout: 5s
retries: 5
kong-migration:
build: .
command: "kong migrations bootstrap"
networks:
- kong_network
restart: on-failure
environment:
KONG_PG_HOST: kong-db
links:
- kong-db
depends_on:
- kong-db
kong:
build: .
restart: always
depends_on:
- kong-migration
- kong-db
healthcheck:
test: ["CMD", "curl", "-f", "http://kong:8001"]
interval: 5s
timeout: 2s
retries: 15
networks:
- kong_network
ports:
- "8000:8000" # Listener
- "8001:8001" # Admin API
- "8443:8443" # Listener (SSL)
- "8444:8444" # Admin API (SSL)
extra_hosts:
- "keycloak-host:192.168.18.247"
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-db
KONG_PG_PORT: 5432
KONG_PG_DATABASE: kong
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_PROXY_LISTEN: 0.0.0.0:8000, 0.0.0.0:8443 ssl
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
KONG_PLUGINS: oidc
keycloak-db:
image: postgres:9.6
volumes:
- keycloak-datastore:/var/lib/postresql/data
networks:
- kong_network
ports:
- "25432:5432"
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
keycloak:
image: jboss/keycloak:4.5.0.Final
restart: always
depends_on:
- keycloak-db
networks:
- kong_network
ports:
- "8180:8080"
environment:
DB_VENDOR: POSTGRES
DB_ADDR: keycloak-db
DB_PORT: 5432
DB_DATABASE: keycloak
DB_USER: keycloak
DB_PASSWORD: password
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
// Dockerfile
FROM kong:1.1.2-alpine
RUN apk update && apk add git unzip curl
ENV KONG_PLUGINS="bundled, oidc"
RUN luarocks install kong-oidc
//通过Konga的Kong配置
Konga在端口1337上运行 Kong管理员为8001,客户Kong为8000
所以我要做的是使用下一个配置创建服务:
{
"host": "192.168.18.247",
"created_at": 1565303126,
"connect_timeout": 60000,
"id": "376ef70a-87af-43ba-92c2-a5d459ccac4f",
"protocol": "http",
"name": "ops",
"read_timeout": 60000,
"port": 3000,
"path": "/api",
"updated_at": 1565303147,
"retries": 5,
"write_timeout": 60000,
"tags": null,
"extras": {
"createdUser": null,
"updatedUser": null,
"kong_node_id": "1",
"service_id": "376ef70a-87af-43ba-92c2-a5d459ccac4f",
"createdAt": "2019-08-08T22:25:26.319Z",
"updatedAt": "2019-08-08T22:25:47.349Z",
"id": 1
}
}
为此服务,我添加了下一条路线:
{
"updated_at": 1565303167,
"created_at": 1565303167,
"strip_path": true,
"snis": null,
"hosts": null,
"name": "ops",
"methods": null,
"sources": null,
"preserve_host": false,
"regex_priority": 0,
"service": {
"host": "192.168.18.247",
"created_at": 1565303126,
"connect_timeout": 60000,
"id": "376ef70a-87af-43ba-92c2-a5d459ccac4f",
"protocol": "http",
"name": "ops",
"read_timeout": 60000,
"port": 3000,
"path": "/api",
"updated_at": 1565303147,
"retries": 5,
"write_timeout": 60000,
"tags": null,
"extras": {
"createdUser": null,
"updatedUser": null,
"kong_node_id": "1",
"service_id": "376ef70a-87af-43ba-92c2-a5d459ccac4f",
"createdAt": "2019-08-08T22:25:26.319Z",
"updatedAt": "2019-08-08T22:25:47.349Z",
"id": 1
}
},
"paths": [
"/ops"
],
"destinations": null,
"id": "1e0ba28b-da93-44d1-9433-ea2bf03340d6",
"protocols": [
"http",
"https"
],
"tags": null
}
我的插件OIDC:
{
"created_at": 1564164342,
"config": {
"response_type": "code",
"introspection_endpoint": "http://keycloak-host:8180/auth/realms/master/protocol/openid-connect/token/introspect",
"filters": null,
"bearer_only": "true",
"ssl_verify": "no",
"session_secret": null,
"introspection_endpoint_auth_method": null,
"realm": "master",
"redirect_after_logout_uri": "/",
"scope": "openid",
"token_endpoint_auth_method": "client_secret_post",
"logout_path": "/logout",
"client_id": "back",
"client_secret": "b1f34901-becc-4f6a-a586-258fef04569c",
"discovery": "http://keycloak-host:8180/auth/realms/master/.well-known/openid-configuration",
"recovery_page_path": null,
"redirect_uri_path": null
},
"id": "bc77d4d7-9fdb-4267-8997-a8187c182ecc",
"service": null,
"name": "oidc",
"protocols": [
"http",
"https"
],
"enabled": true,
"run_on": "first",
"consumer": null,
"route": null,
"tags": null
}
我在Keycloak中的配置是下一个:
我已经创建了两个客户端,一个用于前端,另一个用于我的前端。
//正面
{
"realm": "MyDemo",
"auth-server-url": "http://localhost:8180/auth",
"ssl-required": "external",
"resource": "front",
"public-client": true,
"confidential-port": 0
}
//返回
{
"realm": "MyDemo",
"bearer-only": true,
"auth-server-url": "http://localhost:8180/auth",
"ssl-required": "external",
"resource": "back",
"credentials": {
"secret": "20f3bcf1-683d-4e1c-98a6-414877e461db"
},
"confidential-port": 0,
"policy-enforcer": {}
}
在我的前端前端,我已将网址配置为后端:
export const API = {
'uri': 'http://localhost:8000/ops/'
};
我已经创建了两个文件来管理keycloak服务:
// keycloak.service.ts
import { Injectable } from '@angular/core';
declare var Keycloak: any;
@Injectable({
providedIn: 'root'
})
export class KeycloakService {
public keycloakAuth: any;
constructor() { }
init(): Promise<any> {
return new Promise((resolve, reject) => {
const config = {
'url': 'http://keycloak-host:8180/auth',
'realm': 'master',
'clientId': 'front',
'credentials': {
'secret': 'd030874e-41bc-4710-b28f-c568e7e66c66'
},
};
this.keycloakAuth = new Keycloak(config);
this.keycloakAuth.init({ onLoad: 'login-required' })
.success(() => {
resolve();
})
.error(() => {
reject();
});
});
}
getToken(): string {
return this.keycloakAuth.token;
}
}
// token.interceptor.ts
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpHeaders
} from '@angular/common/http';
import { KeycloakService } from './keycloak.service';
import { Observable } from 'rxjs';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private kcService: KeycloakService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log("BIngo!!!!!!!!!");
const authToken = this.kcService.getToken() || '';
request = request.clone({
// setHeaders: {
// 'Authorization': 'Bearer ' + authToken
// }
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + authToken
})
});
console.log(authToken);
return next.handle(request);
}
}