Keycloak- Angular-Rest Integration - 角色总是空的
Keycloak- Angular-Rest Integration - Roles are always empty
当我读到有关将 keycloak 与 Angular+REST 应用程序集成时,我大多看到一种方法有两个客户端,一个 public 和一个仅承载。这是最好的解决方案还是我可以为这两个应用程序使用一个机密客户端。我读到为 javascript 使用机密客户端并不是最好的方法,因为无法将秘密隐藏在 javascript.
中
此外,在使用两个客户端方法将 keycloak 集成到 rest 和 UI 项目后,身份验证似乎可以正常工作。但我在其余方面没有任何角色。我正在为后端使用 spring 安全适配器和 springboot 1.5.18。我的 keycloak 服务器版本是 3.4.12,keycloak spring 适配器版本是 3.4.3。下面还提供了Keycloak配置文件。
keycloak.json(Angular 项目)
{
"realm": "dev",
"auth-server-url": "https://<keycloakserver> /auth",
"resource": "frontend-dev",
"public-client": true,
"use-resource-role-mappings": true,
"confidential-port": 0,
"ssl-required": "external",
"disable-trust-manager": true
}
application.properties(spring引导)
keycloak.realm=dev
keycloak.bearer-only=true
keycloak.auth-server-url=https:// <keycloakserver> /auth
keycloak.resource= backend-dev
keycloak.use-resource-role-mappings=true
keycloak.credentials.secret=222-3333-4444-5555
#development only properties
keycloak.ssl-required=external
keycloak.disable-trust-manager=true
Keycloak Java 配置
@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
/**
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
public FilterRegistrationBean
keycloakAuthenticationProcessingFilterRegistrationBean(KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken accessToken() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
return ((KeycloakSecurityContext)((KeycloakAuthenticationToken) request.getUserPrincipal()).getCredentials())
.getToken();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests().antMatchers("/**").permitAll();
}
}
为了保护 rest 资源,使用了注解
@RolesAllowed(“Name of the role”)
即使在为用户分配客户端角色后,它仍会抛出 403-拒绝访问错误
我还尝试使用代码
手动获取角色
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.getAuthentication().getAuthorities();
但它总是返回一个空数组。
我终于解决了这个问题。问题出在前端 keycloak 客户端中缺少范围配置。
由于安全原因,所有客户的全部范围都已关闭。因此,除非我们在前端客户端的客户端范围配置中明确设置以包含后端客户端角色,否则它不会成为令牌的一部分。
当我读到有关将 keycloak 与 Angular+REST 应用程序集成时,我大多看到一种方法有两个客户端,一个 public 和一个仅承载。这是最好的解决方案还是我可以为这两个应用程序使用一个机密客户端。我读到为 javascript 使用机密客户端并不是最好的方法,因为无法将秘密隐藏在 javascript.
中此外,在使用两个客户端方法将 keycloak 集成到 rest 和 UI 项目后,身份验证似乎可以正常工作。但我在其余方面没有任何角色。我正在为后端使用 spring 安全适配器和 springboot 1.5.18。我的 keycloak 服务器版本是 3.4.12,keycloak spring 适配器版本是 3.4.3。下面还提供了Keycloak配置文件。
keycloak.json(Angular 项目)
{
"realm": "dev",
"auth-server-url": "https://<keycloakserver> /auth",
"resource": "frontend-dev",
"public-client": true,
"use-resource-role-mappings": true,
"confidential-port": 0,
"ssl-required": "external",
"disable-trust-manager": true
}
application.properties(spring引导)
keycloak.realm=dev
keycloak.bearer-only=true
keycloak.auth-server-url=https:// <keycloakserver> /auth
keycloak.resource= backend-dev
keycloak.use-resource-role-mappings=true
keycloak.credentials.secret=222-3333-4444-5555
#development only properties
keycloak.ssl-required=external
keycloak.disable-trust-manager=true
Keycloak Java 配置
@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
/**
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
public FilterRegistrationBean
keycloakAuthenticationProcessingFilterRegistrationBean(KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken accessToken() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
return ((KeycloakSecurityContext)((KeycloakAuthenticationToken) request.getUserPrincipal()).getCredentials())
.getToken();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests().antMatchers("/**").permitAll();
}
}
为了保护 rest 资源,使用了注解
@RolesAllowed(“Name of the role”)
即使在为用户分配客户端角色后,它仍会抛出 403-拒绝访问错误
我还尝试使用代码
手动获取角色 SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.getAuthentication().getAuthorities();
但它总是返回一个空数组。
我终于解决了这个问题。问题出在前端 keycloak 客户端中缺少范围配置。 由于安全原因,所有客户的全部范围都已关闭。因此,除非我们在前端客户端的客户端范围配置中明确设置以包含后端客户端角色,否则它不会成为令牌的一部分。