Angular 无法在 Spring 使用 Keycloak 启动时获取请求抛出 403
Angular cannot GET request on Spring boot with Keycloak throws 403
我使用 Keycloak 创建了 spring 启动服务。我实现了登录端点。当我通过 Postman 登录服务时,我可以连接到 keycloak 并获取令牌。我可以在其他请求调用中成功使用此令牌。当我使用 angular 登录时,我仍然是令牌,但每次在 spring 启动时请求 returns 403 错误。当我在邮递员中使用相同的令牌时,没有问题。
KeycloakSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Value("${server.servlet.context-path}")
public String contextPath;
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/auth/login").permitAll()
.anyRequest().authenticated()
.and().cors()
.and().csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
@Override
protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(this.authenticationManagerBean());
filter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy());
filter.setAuthenticationFailureHandler(new CustomKeycloakAuthenticationFailureHandler());
return filter;
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
application.yaml
keycloak:
realm: <realm_name>
auth-server-url: http://localhost:8287/auth/
resource: mm-service-1
credentials:
secret: bla-bla-bla
use-resource-role-mappings: false
cors: true
bearer-only: true
enabled: true
public-client: true
JwtInteceptor
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private accountService: AccountService) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add account header with jwt if user is logged in and request is to the api url
const user = this.accountService.userValue;
const isLoggedIn = user && user.token;
const isApiUrl = request.url.startsWith(Constants.SERVER_BASE_PATH);
console.log('REQUEST: ', request);
if (isLoggedIn && isApiUrl) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${user.token}`,
'withCredentials': `true`,
'Access-Control-Allow-Credentials': `true`,
}
});
}
console.log('NEW REQUEST: ', request);
return next.handle(request);
}
}
在 Angular
获取请求
getListMachine(): void {
this.machineApi.listMachine(null, null, null, null, null, 'response')
.pipe(takeUntil(this.unsubscribeAll))
.subscribe((res: any) => {
const resHeader = res.headers;
this.totalRows = resHeader.get('X-Total-Count');
this.machineInfos = res.body;
}, (err) => {
console.error('Err:', err);
});
}
Origin Config
@Configuration
public class ApiOriginCorsConfigurer {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS")
.allowedOriginPatterns("*")
.exposedHeaders(
"Content-Type",
"Accept",
"Authorization",
"link",
"content-range",
"x-total-count",
"location",
"etag",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials")
.allowedHeaders("*")
.allowCredentials(true)
;
}
};
}
}
邮递员请求
Angular请求
如果相同的令牌在邮递员中有效;可能 angular 应用程序有问题。
在 angular
请求中检查您的“授权”header
终于找到问题了。我禁用了 keycloak 的 cors 并且它有效。但是当我想使用cors时,我不知道该怎么做。
如果我是你,我会将这一行 logging.level.org.springframework.security=debug
添加到 application.properties,然后使用 CORS 或不使用它来观察你的应用程序的行为。
希望对你有所帮助。
我使用 Keycloak 创建了 spring 启动服务。我实现了登录端点。当我通过 Postman 登录服务时,我可以连接到 keycloak 并获取令牌。我可以在其他请求调用中成功使用此令牌。当我使用 angular 登录时,我仍然是令牌,但每次在 spring 启动时请求 returns 403 错误。当我在邮递员中使用相同的令牌时,没有问题。
KeycloakSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Value("${server.servlet.context-path}")
public String contextPath;
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/auth/login").permitAll()
.anyRequest().authenticated()
.and().cors()
.and().csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
@Override
protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(this.authenticationManagerBean());
filter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy());
filter.setAuthenticationFailureHandler(new CustomKeycloakAuthenticationFailureHandler());
return filter;
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
application.yaml
keycloak:
realm: <realm_name>
auth-server-url: http://localhost:8287/auth/
resource: mm-service-1
credentials:
secret: bla-bla-bla
use-resource-role-mappings: false
cors: true
bearer-only: true
enabled: true
public-client: true
JwtInteceptor
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private accountService: AccountService) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add account header with jwt if user is logged in and request is to the api url
const user = this.accountService.userValue;
const isLoggedIn = user && user.token;
const isApiUrl = request.url.startsWith(Constants.SERVER_BASE_PATH);
console.log('REQUEST: ', request);
if (isLoggedIn && isApiUrl) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${user.token}`,
'withCredentials': `true`,
'Access-Control-Allow-Credentials': `true`,
}
});
}
console.log('NEW REQUEST: ', request);
return next.handle(request);
}
}
在 Angular
获取请求 getListMachine(): void {
this.machineApi.listMachine(null, null, null, null, null, 'response')
.pipe(takeUntil(this.unsubscribeAll))
.subscribe((res: any) => {
const resHeader = res.headers;
this.totalRows = resHeader.get('X-Total-Count');
this.machineInfos = res.body;
}, (err) => {
console.error('Err:', err);
});
}
Origin Config
@Configuration
public class ApiOriginCorsConfigurer {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS")
.allowedOriginPatterns("*")
.exposedHeaders(
"Content-Type",
"Accept",
"Authorization",
"link",
"content-range",
"x-total-count",
"location",
"etag",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials")
.allowedHeaders("*")
.allowCredentials(true)
;
}
};
}
}
邮递员请求
Angular请求
如果相同的令牌在邮递员中有效;可能 angular 应用程序有问题。 在 angular
请求中检查您的“授权”header终于找到问题了。我禁用了 keycloak 的 cors 并且它有效。但是当我想使用cors时,我不知道该怎么做。
如果我是你,我会将这一行 logging.level.org.springframework.security=debug
添加到 application.properties,然后使用 CORS 或不使用它来观察你的应用程序的行为。
希望对你有所帮助。