【问题标题】:Spring Security HttpSecurity configSpring Security HttpSecurity 配置
【发布时间】:2020-03-04 06:51:53
【问题描述】:

我试图了解 RequestMatcher、AntMatcher 等是如何工作的。我阅读了一些帖子并了解了基础知识。其实我有这个简单的基本配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.requestMatchers() //1
        .antMatchers("/login", "/oauth/authorize") //2
        .and() //3
        .authorizeRequests() //4
        .anyRequest() //5
        .authenticated() //6;

我真的不明白第 1,2 和 3 点。据我了解,这意味着 /login/oauth/authorize 的请求已映射并且应该是授权请求。所有其他请求都需要验证。

意味着端点/user/me 我必须进行身份验证,因为它由第 5 点和第 6 点统治? 对这个端点的调用对我有用。

在我的其他配置中,我尝试了不同的方法:

@Override
protected void configure(HttpSecurity http) throws Exception { // @formatter:off
      http
       .authorizeRequests() //1
        .antMatchers("/login", "/oauth/authorize", "/img/**").permitAll() //2
        .anyRequest() //3
        .authenticated() //4

在我看来,这应该与第一个配置的逻辑相同。但实际上端点/user/me 不再可访问。

非常感谢您的澄清


更新 1:

这是我现在的配置:

@Override
protected void configure(HttpSecurity http) throws Exception { // @formatter:off
    http
        .requestMatchers()
           .antMatchers("/", "/login", "/oauth/authorize", 
               "/main", "/logout-success", "/single-logout",
               "/password_forgotten", "/enter_new_password", "/img/**",
               "/logout", "/access_denied")
            .and().authorizeRequests()
                .antMatchers("/img/**", "/logout-success", "/password_forgotten",
                    "/enter_new_password", "/access_denied").permitAll()
            .requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
            .and()
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .failureUrl("/login?error")
            .defaultSuccessUrl("/main")
            .permitAll()
            .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/logout-success")
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true)
            .and()
            .exceptionHandling()
            .accessDeniedPage("/access_denied")
            .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
            .and().csrf().disable();

如果我以未经身份验证的用户身份输入 URL \user\me,我会收到 401 和以下消息:

<oauth>
<error_description>
Vollständige Authentifikation wird benötigt um auf diese Resource zuzugreifen
</error_description>
<error>unauthorized</error>
</oauth>

这没问题,但意味着任何其他 SecurityFilterChain 都发生在这个 URL 上,对吧?

【问题讨论】:

    标签: java spring spring-boot spring-security spring-oauth2


    【解决方案1】:

    requestMatchers() 配置 URL 是否将由该 SecurityFilterChain 处理。所以如果一个 URL 不匹配它,整个 SecurityFilterChain 将被跳过,这意味着 Spring Security 将不会处理这个 URL。如果不配置,默认匹配所有网址。

    authorizeRequests() 为 URL 配置授权内容,例如是否需要对其进行身份验证或是否只有某些角色可以访问它等。它仅对由该 SecurityFilterChain 处理的那些 URL 有效(即那些requestMatchers()匹配的URL)

    所以,回到你的第一个例子:

      http.requestMatchers() //1
            .antMatchers("/login", "/oauth/authorize") //2
            .and() //3
            .authorizeRequests() //4
            .anyRequest() //5
            .authenticated() //6;
    

    这意味着这个 SecurityFilterChain 只会对/login/oauth/authorize 有效。这两个 URL 都需要经过身份验证。此 SecurityFilterChain 不会处理所有其他 URL。所以/user/me是否需要认证与Spring Security无关。

    http
           .authorizeRequests() //1
            .antMatchers("/login", "/oauth/authorize", "/img/**").permitAll() //2
            .anyRequest() //3
            .authenticated() //4
    

    这意味着所有的 URL 都会被这个 SecurityFilterChain 处理(默认值requestMatchers())。 /login/oauth/authorize/img/** 不需要任何授权。其他 URL 需要进行身份验证。

    【讨论】:

    • 非常感谢您的澄清。例如1表示authorizeRequests()anyRequest()只是属于之前定义的antMatchers,不影响其他url。也意味着/login 需要身份验证。因此,如果我第一次输入此 URL,spring 会自动使我成为 AnonymousUser,直到我真正进行身份验证,对吗? /user/me 出现的原因是,如果我没有被授权(在示例 1 中),这个资源确实是安全的。所以肯定有另一个 securityFilterChain 来检查这个 url,对吧?
    • 是的。你说的对。 /user/me 有可能被另一个 securityFilterChain 处理。建议你通过@EnableWebSecurity(debug=true)开启调试模式,并将security security的日志级别设置为debug(logging.level.org.springframework.security.web=DEBUG)。然后它将打印用于处理 URL 请求的 securityFilterChain 的信息,以便您检查 /user/me 和其他 URL 之间是否有任何差异
    【解决方案2】:

    您的第一个配置
    .requestMtchers() //1

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers() //1
            .antMatchers("/login", "/oauth/authorize") //2
            .and() //3
            .authorizeRequests() //4
            .anyRequest() //5
            .authenticated() //6;
    

    让我解释一下你的.authorizeRequests() //4

    http.authorizeRequests()这是一个通配符(/**)(就像过滤器允许每个请求一样)
    HttpSecurity 配置将只考虑具有这些模式的请求 在这里你可以说

    http.authorizeRequests()
    //is nothing but equals to
    http.antMatcher("/**").authorizeRequests();
    //and also equals to
    http.requestMatchers()
                .antMatchers("/**")
                .and()
                .authorizeRequests()
    
    

    如果你像下面这样配置

    http.antMatcher("/api/**").authorizeRequests();
    

    只有在传入的请求 uri 与配置的 antmatcher(/api/**) 匹配时才会查询其余配置(.hasRole().hasAnyRole.authenticated().authenticated()

    假设您需要配置多个 URL(不同的模式),那么您不能只使用一个 antMatcher。你需要多个然后你应该使用 requestMatcher 如下

    http.requestMatchers()
                .antMatchers("/api/**", "employee/**", "/customer/**")
                .and()
                .authorizeRequests()
    

    .antMatchers() //2
    用于配置RequestMatcherConfigurer的返回类型.requestMatchers()
    或者也
    用于配置ExpressionInterceptUrlRegistry返回类型.authorizeRequests()

    .and() //3

    返回 HttpSecurity 以进行进一步的自定义

    .anyRequest() //5

    创建RequestMatcher后被链接的对象

    所有请求都匹配配置的请求匹配器模式

    .authenticated() //6
    下面的配置是自我解释的

    .antMatchers("/app/admin/**").hasRole("ADMIN")
    //or
    .antMatchers("/app/admin/**").hasAnyRole("ADMIN", "USER")
    //or
    .antMatchers("/app/admin/**").authenticated()
    //or
    .antMatchers("/app/admin/**").permitAll()
    

    这是关于antMatchers、authorizeRequests和authenticated的粗略想法。您可以在此链接中参考我的答案for sequence of execution in spring security

    【讨论】:

      猜你喜欢
      • 2017-10-18
      • 2016-08-08
      • 2021-06-29
      • 1970-01-01
      • 2016-03-14
      • 2017-09-21
      • 2021-07-04
      • 2023-01-17
      • 2021-12-15
      相关资源
      最近更新 更多