我实现了一个自定义的身份验证过滤器,效果很好。在设置会话并将身份验证对象添加到安全上下文后,我使用外部身份提供程序并重定向到最初请求的URL。
安全配置
@EnableWebSecurity(debug = true)
@Configuration
class SecurityConfig extends WebSecurityConfigurerAdapter {
// this is needed to pass the authentication manager into our custom security filter
@Bean
@Override
AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean()
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
//.antMatchers("/admin/test").hasRole("METADATA_CURATORZ")
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new CustomSecurityFilter(authenticationManagerBean()), UsernamePasswordAuthenticationFilter.class)
}
}
过滤逻辑
目前,我的自定义过滤器(身份确认后)只需硬编码一个角色:
SimpleGrantedAuthority myrole = new SimpleGrantedAuthority("METADATA_CURATORZ")
return new PreAuthenticatedAuthenticationToken(securityUser, null, [myrole])
然后将该身份验证对象(上面返回)添加到我的SecurityContext,然后再重定向到所需的endpoint:
SecurityContextHolder.getContext(). setAuthentiation(身份验证)
控制器终结点
@RequestMapping(path = '/admin/test', method = GET, produces = 'text/plain')
String test(HttpServletRequest request) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication()
String roles = auth.getAuthorities()
return "roles: ${roles}"
}
然后,该endpoint在浏览器中生成响应:
“角色:[METADATA\u CURATORZ]”
太好了。所以我的身份验证和将角色应用于我的用户效果很好。
现在,如果我从安全配置中取消注释这一行:
/。antMatchers(“/admin/test”)。hasRole(“METADATA\u CURATORZ”)
我再也无法访问该资源并获得403——尽管我们已经证明角色已经设置好了。
这对我来说似乎完全是荒谬的,但我不是Spring Security专家。
我可能错过了一些非常简单的事情。有什么想法吗?
我有一些问题:
我的自定义过滤器是否需要放在特定内置过滤器之前,以确保在执行该过滤器后执行授权步骤?
您的过滤器必须位于FilterSecurityInterceptor之前,因为这是进行授权和身份验证的地方。此过滤器是最后调用的过滤器之一。
现在关于过滤器的最佳位置可能在哪里,这真的取决于情况。例如,您真的希望您的过滤器位于匿名认证过滤器
之前,因为如果没有,未经身份验证的用户将始终使用匿名认证令牌
进行“身份验证”到您的过滤器被调用时。
您可以在FilterComparator中查看过滤器的默认顺序。AbstractPreAuthenticatedProcessingFilter几乎与您正在做的事情相对应,它按过滤器的顺序排列,让您知道可以将自己的过滤器放在哪里。无论如何,过滤器的顺序应该没有问题。
在请求周期中何时进行antMatcher/hasRole检查?
所有这些都发生在FilterSecurityInterceptor中,更准确地说,发生在其父级AbstractSecurityInterceptor中:
protected InterceptorStatusToken beforeInvocation(Object object) {
Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource()
.getAttributes(object);
if (attributes == null || attributes.isEmpty()) {
...
}
...
Authentication authenticated = authenticateIfRequired();
// Attempt authorization
try {
this.accessDecisionManager.decide(authenticated, object, attributes);
}
catch (AccessDeniedException accessDeniedException) {
...
throw accessDeniedException;
}
额外信息:本质上,FilterSecurityInterceptor
有一个包含Map的
ExpressionBasedFilterInvocationSecurityMetadataSource
我是否需要更改我在安全配置链中调用的顺序,以及我应该如何理解当前编写的配置?很明显,它没有做我认为应该做的事情。
不,你的过滤器应该没有任何问题。作为补充说明,除了您的配置(HttpSecurity http)方法之外,您扩展的websecurityconfig适配器还有一些默认值:
http
.csrf().and()
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling().and()
.headers().and()
.sessionManagement().and()
.securityContext().and()
.requestCache().and()
.anonymous().and()
.servletApi().and()
.apply(new DefaultLoginPageConfigurer<>()).and()
.logout();
如果您想确切了解它们的作用以及它们添加了什么过滤器,可以查看HttpSecurity。
当您执行以下操作时:
.authorizeRequests()
.antMatchers("/admin/test").hasRole("METADATA_CURATORZ")
...搜索的角色是
"ROLE_METADATA_CURATORZ"
。为什么?ExpressionUrlAuthorizationConfigrer
的静态hasRole(String角色)
方法最终处理"METADATA_CURATORZ"
:
if (role.startsWith("ROLE_")) {
throw new IllegalArgumentException(
"role should not start with 'ROLE_' since it is automatically inserted. Got '"
+ role + "'");
}
return "hasRole('ROLE_" + role + "')";
}
因此,您的授权表达式变为“hasRole('ROLE\u METADATA\u CURATORZ')”
,这最终调用了SecurityExpressionRoot上的方法
hasRole('ROLE\u METADATA\u CURATORZ')
,该方法反过来在Authentication
的权限中搜索角色。
改变
SimpleGrantedAuthority myrole = new SimpleGrantedAuthority("METADATA_CURATORZ");
到:
SimpleGrantedAuthority myrole = new SimpleGrantedAuthority("ROLE_METADATA_CURATORZ");
问题内容: 这是我的情况: 一个Web应用程序对许多应用程序执行某种SSO 登录的用户,而不是单击链接,该应用就会向正确的应用发布包含用户信息(名称,pwd [无用],角色)的帖子 我正在其中一个应用程序上实现SpringSecurity以从其功能中受益(会话中的权限,其类提供的方法等) 因此,我需要开发一个 自定义过滤器 -我猜想-能够从请求中检索用户信息,通过自定义 DetailsUserSe
现在我的是的一部分,位于正确的位置。平滑。 但是,由于是,它会被引导拾取并作为筛选器包含。所以我的过滤链看起来真的像: SSOAuthenticationFilter(由于是,因此包含) FilterChainProxy(spring自动配置) ... SecurityContextPersistenceFilter SSOAuthenticationFilter(包含在) ... 显然,我希望在
嗨,我正在学习Spring安全,我被困在自定义认证过滤器中。我有以下文件:主应用程序文件: : 我的安全配置文件安全: 最后我的CustomAuthentication filter文件:< code > customauthenticationfilter . Java : 因此,我已经将<code>attemptAuthentication</code>方法放在日志中,但似乎请求没有到达那里。
我的问题是我的SpringConfig类中筛选器的配置。我希望筛选器仅在请求是/authenticate URL时生效,我已将.antmatcher(“/authenticate/**”)添加到筛选器配置中。 当所有其他URL中的该行不再安全时,我可以手动导航到/home,而不进行身份验证,删除该行并对/home进行身份验证。 我应该声明一个只适用于特定URL的筛选器吗? 我如何在维护其他URL的
我正在尝试实现一个自定义密钥克拉克身份验证器SPI,用于针对外部数据源/REST服务进行身份验证。计划是将它们迁移到Keycloak。 成功后,在keycloak数据源上创建用户。 创建自定义映射器以在令牌上添加额外的用户属性。 我正在遵循官方指南https://www.keycloak.org/docs/latest/server_development/index.html#_auth_spi
我试图使用keycloak只用于身份验证,并有自己的自定义过滤器用于授权。因此理想的流程是:首先,Keycloak filter对请求进行身份验证,并在上下文中设置身份验证对象。然后,我的自定义过滤器应该运行,它应该获得现有的身份验证对象,在该身份验证对象中添加权限,并将其设置回上下文中。 因此,首先,在speing引导应用程序中使用keycloak是正确的方法吗?如果是,那么如何使我的过滤器在过