问题描述
我的公司使用Keycloak进行身份验证,该身份验证与LDAP连接并返回填充有公司数据的用户对象.然而,在此期间,我们所有人都在家工作,并且在我的日常工作中,每次我重新加载应用程序时都必须在公司服务器中进行身份验证,这被证明是昂贵的开销.尤其是间歇性的Internet连接.
My company uses Keycloak for authentication connected with LDAP and returning a user object filled with corporative data.Yet in this period we are all working from home and in my daily work having to authenticate in my corporative server every time I reload the app, has proven to be an expensive overhead. Especially with intermittent internet connections.
如何伪造Keycloak调用并使成功后的keycloak.protect()工作?
How can I fake the Keycloak call and make keycloak.protect() work as it has succeeded?
我可以在计算机上安装Keyclock服务器,但我不愿意这样做,因为它可能是其中运行的另一台服务器,除了流浪的VM,Postgres服务器,be server以及我打开的所有其他设备.最好进行模拟调用并返回固定的硬编码对象.
I can install a Keyclock server in my machine, but I'd rather not do that because it would be another server running in it besides, vagrant VM, Postgres server, be server, and all the other things I leave open.It would be best to make a mock call and return a fixed hard-coded object.
我的项目的app-init.ts是这样的:
My project's app-init.ts is this:
import { KeycloakService } from 'keycloak-angular';
import { KeycloakUser } from './shared/models/keycloakUser';
<...>
export function initializer(
keycloak: KeycloakService,
<...>
): () => Promise<any> {
return (): Promise<any> => {
return new Promise(async (res, rej) => {
<...>
await keycloak.init({
config: environment.keycloakConfig,
initOptions: {
onLoad: 'login-required',
// onLoad: 'check-sso',
checkLoginIframe: false
},
bearerExcludedUrls: [],
loadUserProfileAtStartUp: false
}).then((authenticated: boolean) => {
if (!authenticated) return;
keycloak.getKeycloakInstance()
.loadUserInfo()
.success(async (user: KeycloakUser) => {
// ...
// load authenticated user data
// ...
})
}).catch((err: any) => rej(err));
res();
});
};
我只需要一个固定的登录用户.但是它必须返回一些固定的自定义数据.像这样:
I just need one fixed logged user. But it has to return some fixed customized data with it. Something like this:
{ username: '111111111-11', name: 'Whatever Something de Paula',
email: '[email protected]', department: 'sales', employee_number: 7777777 }
编辑
我试图查看@BojanKogoj的想法,但来自Angular Interceptor页面以及其他示例和教程的AFAIU必须将其注入组件中. Keycloak初始化是在应用程序初始化而不是组件中调用的. Keycloak的返回也不是init()方法的直接返回.它以.getKeycloakInstance().loadUserInfo().success()
顺序穿过其他对象.也许只是我不完全了解它.如果有人可以提供拦截器的示例,它可以拦截呼叫并返回正确的结果,则可能.
I tried to look at the idea of @BojanKogoj but AFAIU from Angular Interceptor page and other examples and tutorials, it has to be injected in a component. Keycloak initialization is called on app initialization, not in a component. Also Keycloak's return is not the direct return of init() method. It passes through other objects in the .getKeycloakInstance().loadUserInfo().success()
sequence.Or maybe it's just me that didn't fully understand it. If anyone can come with an example of an interceptor that can intercept the call and return the correct result, that could be a possibility.
Edit2
只需补充一下,我所需要的就是使整个密钥斗篷的系统正常工作.请注意,(user: KeycloakUser) => {
函数已传递给keycloak内部系统的success
方法.如前所述,路由具有必须起作用的keycloak.protect().因此,这不仅仅是与用户一起返回承诺的简单案例.整个.getKeycloakInstance().loadUserInfo().success()链都必须被模拟.至少我是这样理解的.
Just to complement that what I need is for the whole keycloak's system to work. Please notice that the (user: KeycloakUser) => {
function is passed to success
method of keycloak's internal system. As I said above, routes have a keycloak.protect() that must work. So it's not just a simple case of returning a promise with a user. The whole .getKeycloakInstance().loadUserInfo().success() chain has to be mocked. Or at least that's how I understand it.
我在基于@yurzui答案的解决方案中包含了答案
将等待几天才能授予赏金,以查看是否有人可以提出更好的解决方案(我对此表示怀疑).
Will wait a couple of days to award the bounty to see if someone can came up with an even better solution (which I doubt).
推荐答案
您可以利用Angular环境(甚至是process.env
)变量在真实和模拟实现之间进行切换.
You can leverage Angular environment(or even process.env
) variable to switch between real and mock implementations.
下面是一个简单的示例:
Here is a simple example of how to do that:
app-init.ts
...
import { environment } from '../environments/environment';
export function initializer(
keycloak: KeycloakService
): () => Promise<any> {
function authenticate() {
return keycloak
.init({
config: {} as any,
initOptions: {onLoad: 'login-required', checkLoginIframe: false},
bearerExcludedUrls: [],
loadUserProfileAtStartUp: false
})
.then(authenticated => {
return authenticated ? keycloak.getKeycloakInstance().loadUserInfo() : Promise.reject();
});
}
// we use 'any' here so you don't have to define keyCloakUser in each environment
const { keyCloakUser } = environment as any;
return () => {
return (keyCloakUser ? Promise.resolve(keyCloakUser) : authenticate()).then(user => {
// ...
// do whatever you want with user
// ...
});
};
}
environment.ts
export const environment = {
production: false,
keyCloakUser: {
username: '111111111-11',
name: 'Whatever Something de Paula',
email: '[email protected]',
}
};
environment.prod.ts
export const environment = {
production: true,
};
更新
如果要在客户端模拟KeycloakService
,则可以告诉Angular依赖注入来处理:
Update
If you want to mock KeycloakService
on client side then you can tell Angular dependency injection to handle that:
app.module.ts
import { environment } from '../environments/environment';
import { KeycloakService, KeycloakAngularModule } from 'keycloak-angular';
import { MockedKeycloakService } from './mocked-keycloak.service';
@NgModule({
...
imports: [
...
KeycloakAngularModule
],
providers: [
{
provide: KeycloakService,
useClass: environment.production ? KeycloakService : MockedKeycloakService
},
{
provide: APP_INITIALIZER,
useFactory: initializer,
multi: true,
deps: [KeycloakService]
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
mocked-keycloak.service.ts
import { Injectable} from '@angular/core';
import { KeycloakService } from 'keycloak-angular';
@Injectable()
class MockedKeycloakService extends KeycloakService {
init() {
return Promise.resolve(true);
}
getKeycloakInstance() {
return {
loadUserInfo: () => {
let callback;
Promise.resolve().then(() => {
callback({
userName: 'name'
});
});
return {
success: (fn) => callback = fn
};
}
} as any;
}
}
这篇关于如何在本地开发中使用伪造的keycloack调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!