我遇到Spring Boot安全问题。我想要的是在Spring Boot中同时为同一个项目进行两种不同的身份验证。一个是除'/ download / export / *'之外的所有路径的SSO(keycloak身份验证),另一个是Spring Boot基本身份验证。 这是我的配置文件:
@Configuration
@EnableWebSecurityp
public class MultiHttpSecurityConfig {
@Configuration
@Order(1)
public static class DownloadableExportFilesSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.antMatcher("/download/export/test")
.authorizeRequests()
.anyRequest().hasRole("USER1")
.and()
.httpBasic(); }
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth.inMemoryAuthentication()
.withUser("user").password("password1").roles("USER1");
}
}
@Configuration
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public static class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(keycloakAuthenticationProvider());
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy()
{
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http
.regexMatcher("^(?!.*/download/export/test)")
.authorizeRequests()
.anyRequest().hasAnyRole("ADMIN", "SUPER_ADMIN")
.and()
.logout().logoutSuccessUrl("/bye");
}
}
以上代码的问题如下: 如果我请求url'/ download / export / test',那么它会询问我的用户名/密码(基本身份验证)。成功登录后,它再次询问我的用户名/密码(但这次是keycloak身份验证),即使从SecurityConfig(Keycloak Adapter)中排除了请求的URL。
它只给我一个警告:
2016-06-20 16:31:28.771 WARN 6872 --- [nio-8087-exec-6] o.k.a.s.token.SpringSecurityTokenStore : Expected a KeycloakAuthenticationToken, but found org.springframework.security.authentication.UsernamePasswordAuthenticationToken@3fb541cc: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER1; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: 4C1BD3EA1FD7F50477548DEC4B5B5162; Granted Authorities: ROLE_USER1
您对如何一起使用keycloak和基本身份验证有什么想法吗?
非常感谢! 卡罗
答案 0 :(得分:6)
您遇到的问题是use strict;
use warnings;
use Time::Piece;
use Time::Seconds;
my $str = '2018-02-05 12:00:00';
my $format = '%Y-%m-%d %H:%M:%S';
my $tp = localtime->strptime($str, $format);
$tp += ONE_HOUR * 48;
print $tp->strftime($format);
拦截了每个使用HTTP授权标头的请求。如果您的请求未通过Keycloak进行身份验证(即使您已通过任何其他身份验证提供程序进行身份验证! - 在您使用基本身份验证的情况下),您始终会被重定向到Keycloak&# 39; s登录页面(在您的情况下)或获取401 Unauthorized(如果KeycloakAuthenticationProcessingFilter.java
中的Keycloak客户端配置为仅承载)。
默认情况下,如果请求与keycloak.json
匹配,则会调用KeycloakAuthenticationProcessingFilter.java
:
KeycloakAuthenticationProcessingFilter.DEFAULT_REQUEST_MATCHER
这意味着任何与DEFAULT_LOGIN_URL( / sso / login ) OR 匹配的请求都包含授权HTTP标头(在您的情况下) OR access_token 作为查询参数,将由public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
new OrRequestMatcher(
new AntPathRequestMatcher(DEFAULT_LOGIN_URL),
new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER),
new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN)
);
处理。
这就是为什么你必须用你自己的实现替换KeycloakAuthenticationProcessingFilter.java
,当你的请求通过基本身份验证进行身份验证时,它会跳过调用RequestHeaderRequestMatcher(AUTHORIZATION_HEADER)
。
以下是一个完整的解决方案,使您可以在相同的路径上同时使用基本身份验证和Keycloak身份验证。请特别注意 IgnoreKeycloakProcessingFilterRequestMatcher 实现,该实现将替换默认的 RequestHeaderRequestMatcher 。此匹配器仅匹配包含授权HTTP标头的请求,该标头的值不以KeycloakAuthenticationProcessingFilter.java
为前缀。
在下面的示例中,具有角色"Basic "
的用户可以访问TESTER
,而具有/download/export/test
或ADMIN
角色的用户可以使用所有其他路径(我认为,在您的角色中) case,是Keycloak服务器上的帐户。)
SUPER_ADMIN
答案 1 :(得分:0)
我通过在KeycloakAuthenticationProcessingFilter上为路径配置例外来解决这个问题:
...
@Configuration
@Order(2)
static class KeyCloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Bean
public KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(
authenticationManagerBean()
, new AndRequestMatcher(
KeycloakAuthenticationProcessingFilter.DEFAULT_REQUEST_MATCHER,
new NegatedRequestMatcher(new AntPathRequestMatcher(YOUR_BASIC_AUTHD_PATH))));
filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
return filter;
}