gpt4 book ai didi

Spring Security 自定义身份验证过滤器和授权

转载 作者:行者123 更新时间:2023-12-03 16:24:40 25 4
gpt4 key购买 nike

我已经实现了一个自定义身份验证过滤器,并且效果很好。我使用外部身份提供程序并在设置 session 并将我的身份验证对象添加到我的安全上下文后重定向到我最初请求的 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 中:
SecurityContextHolder.getContext().setAuthentication(authentication)
Controller 端点
  @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}"
}

这个端点然后在浏览器中产生一个响应:

"roles: [METADATA_CURATORZ]"



伟大的。因此,我的身份验证和将角色应用于我的用户效果很好。

现在,如果我从安全配置中取消注释这一行:
//.antMatchers("/admin/test").hasRole("METADATA_CURATORZ")
我无法再访问该资源并收到 403 - 即使我们已经证明该角色已设置。

这对我来说似乎完全荒谬且 splinter ,但我不是 Spring Security 专家。

我可能错过了一些非常简单的东西。有任何想法吗?

我有一些问题:
  • 我的自定义过滤器是否需要放置在特定的内置过滤器之前,以确保在执行该过滤器之后进行授权步骤?
  • 在请求周期中何时进行 antMatcher/hasRole 检查?
  • 我是否需要更改我在安全配置链中调用的顺序,以及我应该如何理解我目前编写的配置?它显然没有做我认为应该做的事情。
  • 最佳答案

    Does my custom filter need to be placed before a specific built-in filter to ensure the authorization step occurs after that filter is executed?



    您的过滤器 必须来之前 FilterSecurityInterceptor ,因为这是授权和身份验证发生的地方。这个过滤器是最后被调用的过滤器之一。

    现在至于过滤器的最佳位置可能在哪里,这真的取决于。例如,您确实希望过滤器位于 AnonymousAuthenticationFilter 之前因为如果没有,未经身份验证的用户将始终通过 AnonymousAuthenticationToken 进行“身份验证”。当您的过滤器被调用时。

    您可以在 FilterComparator 中查看过滤器的默认顺序. AbstractPreAuthenticatedProcessingFilter几乎与您正在做的事情相对应 - 它按照过滤器的顺序放置可以让您了解可以放置您的过滤器的位置。无论如何,您的过滤器的顺序应该没有问题。

    When in the request cycle is the antMatcher/hasRole check taking place?



    所有这一切都发生在 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有一个 ExpressionBasedFilterInvocationSecurityMetadataSource包含 Map<RequestMatcher, Collection<ConfigAttribute>> .在运行时,您的请求会根据 Map 进行检查看看有没有 RequestMatcher关键是匹配。如果是,则为 Collection<ConfigAttribute>传递给 AccessDecisionManager ,最终要么授予访问权限,要么拒绝访问。默认 AccessDecisionManagerAffirmativeBased并包含处理 WebExpressionVoter 集合的对象(通常是 ConfigAttribute )并通过反射调用 SpelExpression对应于您的 "hasRole('METADATA_CURATORZ')"反对 SecurityExpressionRoot用您的 Authentication 初始化的对象.

    Do I need to change the order of what I am calling in my security configure chain, and how should I understand the config as I've currently written it? It's obviously not doing what I think it should be.



    不,您的过滤器应该没有任何问题。作为旁注,除了您在 configure(HttpSecurity http) 中拥有的内容之外方法, WebSecurityConfigurerAdapter你扩展自有一些默认值:
    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" .为什么? ExpressionUrlAuthorizationConfigurer的静态 hasRole(String role)方法结束处理 "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_METADATA_CURATORZ'"这最终会调用方法 hasRole('ROLE_METADATA_CURATORZ')SecurityExpressionRoot ,依次搜索角色 ROLE_METADATA_CURATORZAuthentication的当局。

    解决方案

    改变
    SimpleGrantedAuthority myrole = new SimpleGrantedAuthority("METADATA_CURATORZ");

    到:
    SimpleGrantedAuthority myrole = new SimpleGrantedAuthority("ROLE_METADATA_CURATORZ");

    关于Spring Security 自定义身份验证过滤器和授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51144558/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com