如何使用KeyClope保护Angular 8前端,以及使用gateway、eureka保护JavaSpring云微服务后端

如何使用KeyClope保护Angular 8前端,以及使用gateway、eureka保护JavaSpring云微服务后端,angular,spring-security,spring-cloud,keycloak,angular-oauth2-oidc,Angular,Spring Security,Spring Cloud,Keycloak,Angular Oauth2 Oidc,提前,我为这个冗长的问题道歉!事实上,这个问题并不长,但我发布了很多代码,因为我不知道什么与我的问题相关或不相关 我一直在尝试制作一个简单的poc: -有棱角的前端 -用于身份验证的密钥斗篷服务器 -Spring云后端架构: -使用Spring云安全保护的Spring云网关 -Spring云Netflix Eureka服务器 -Spring云配置服务器 -使用Spring Security OAuth2保护的一些Springboot微服务 无法工作:我无法让Angular应用程序访问受保护的后端

提前,我为这个冗长的问题道歉!事实上,这个问题并不长,但我发布了很多代码,因为我不知道什么与我的问题相关或不相关

我一直在尝试制作一个简单的poc: -有棱角的前端 -用于身份验证的密钥斗篷服务器 -Spring云后端架构: -使用Spring云安全保护的Spring云网关 -Spring云Netflix Eureka服务器 -Spring云配置服务器 -使用Spring Security OAuth2保护的一些Springboot微服务 无法工作:我无法让Angular应用程序访问受保护的后端URI并从中获取任何数据。我得到一个
401未经授权的
响应。如果我将断点指向MS-Spring-secu过滤器,则在
HttpServletRequest请求中没有任何令牌

工作: -使用前端通过角度进行身份验证 -Angular可以从后端未受保护的URI获取数据 -邮递员在OAuth2授权类型设置为资源所有者密码凭据的受保护后端URI上进行测试

我学习了很多教程,但这本教程的效果更好:

以下是我认为相关的代码:

棱角分明

我使用了这个OAuth库:

    • 应用模块*
@NgModule({
声明:[
应用组件,
书籍组件,
头部组件,
侧导航组件
],
进口:[
浏览器模块,
BrowserAnimationsModule,
HttpClientModule,
批准模块,
反应形式模块,
OAuthModule.forRoot({
资源服务器:{
允许URL:['http://localhost:4200'],
sendAccessToken:true
}
}),
AuthConfigModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule
],
供应商:[
图书馆警卫,
{提供:HTTP_拦截器,
useClass:DefaultOAuthInterceptor,
多:真的
}
],
entryComponents:[AppComponent],
引导:[AppComponent]
})
导出类AppModule{
}
    • 海关警卫*
@Injectable()
导出类CustomAuthGuard实现CanActivate{
构造函数(专用oauthService:oauthService,受保护路由器:路由器){
}
canActivate(路由:ActivatedRouteSnapshot,状态:RouterStateSnashot):任意{
const hasIdToken=this.oauthService.hasvalidtoken();
const hasAccessToken=this.oauthService.hasValidAccessToken();
if(this.oauthService.hasValidAccessToken()){
返回(hasIdToken&&hasAccessToken);
}
this.router.navigate([this.router.url]);
返回此.oauthService.loadDiscoveryDocumentAndLogin();
}
}
    • 默认OAuthinterceptor*
@Injectable()
导出类DefaultOAuthInterceptor实现HttpInterceptor{
建造师(
专用authStorage:OAuthStorage,
专用oauthService:oauthService,
私有errorHandler:OAuthResourceServerErrorHandler,
@可选()专用模块配置:OAuthModuleConfig
) {
}
私有checkUrl(url:string):布尔值{
const found=this.moduleConfig.resourceServer.allowedUrls.find(u=>url.startsWith(u));
返回!!找到了;
}
公共截获(req:HttpRequest,next:HttpHandler):可观察{
console.log('INTERCEPTOR');
const url=req.url.toLowerCase();
如果(!this.moduleConfig){返回下一个.handle(req);}
如果(!this.moduleConfig.resourceServer){return next.handle(req);}
如果(!this.moduleConfig.resourceServer.allowedUrls){return next.handle(req);}
如果(!this.checkUrl(url)){return next.handle(req);}
const sendAccessToken=this.moduleConfig.resourceServer.sendAccessToken;
if(sendAccessToken){
//const token=this.authStorage.getItem('access_token');
const token=this.oauthService.getIdToken();
const头文件=‘承载人’+令牌;
log('拦截器中的令牌:'+令牌);
const headers=req.headers
.set('授权',标题);
req=req.clone({headers});
}
返回next.handle(req)/*.catch(err=>this.errorHandler.handleError(err))*/;
}
}
    • AuthConfig*
export const authConfig:authConfig={
发卡机构:environment.keydeport.issuer,
redirectUri:environment.keydeport.redirectUri,
clientId:environment.keydape.clientId,
dummyClientSecret:environment.keydape.dummyClientSecret,
responseType:environment.keydeport.responseType,
范围:environment.keydeport.scope,
requireHttps:environment.keydeport.requireHttps,
//JWT令牌中不存在at_哈希
showDebugInformation:environment.keydeport.showDebugInformation,
DisableThashCheck:environment.keydapore.DisableThashCheck
};
导出类OAuthModuleConfig{
resourceServer:OAuthResourceServerConfig={sendAccessToken:false};
}
导出类OAuthResourceServerConfig{
/**
*应拦截其调用的URL。
*如果注册了ResourceServerErrorHandler,则会将其用于它们。
*如果sendAccessToken设置为true,则访问令牌也将发送给它们。
*/
allowedUrls?:数组;
sendAccessToken=true;
customUrlValidation?:(url:string)=>布尔值;
}
    • AuthConfigService*
@Injectable()
导出类AuthConfigService{
私有令牌:任何;
私人代币:任何;
建造师(
专用只读oauthService:oauthService,
私有只读authConfig:authConfig
) {
}
异步initAuth():承诺{
返回新承诺((resolveFn,rejectFn)=>{
//安装oauthService
this.oauthService.configure(this.authConfig);
this.oauthService.setStorage(本地存储);
this.oauthService.tokenValidationHandler=新的NullValidationHandler();
//潜艇