当前位置: 首页 > 知识库问答 >
问题:

多个WebSecurityConfigrerAdapters:Spring Security中的JWT身份验证和表单登录

伍玮
2023-03-14

我有spring boot应用程序和thymeleaf。我正在使用spring security formLogin方法来实现安全性,现在我只需要为一些API添加JWT。


@EnableWebSecurity
public class SecurityConfigurations {
    @Autowired
    UserDetailsServiceImpl userDetails;

    @Bean
    DaoAuthenticationProvider provider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(encoder());
        provider.setUserDetailsService(userDetails);
        return provider;
    }

    @Bean
    PasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

    @Configuration
    @Order(1)

    public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {

        @Autowired
        private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

        @Autowired
        private JwtRequestFilter jwtRequestFilter;

        @Autowired
        DaoAuthenticationProvider provider;

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(provider);
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {

            httpSecurity.csrf().disable()

                    .authorizeRequests().antMatchers("/api/user/authenticate").permitAll()

                    .antMatchers("/api/user/**").hasRole("USER")
                    .and().
                    exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

            // Add a filter to validate the tokens with every request
            httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }

    @Configuration
    public static class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
        @Autowired
        DaoAuthenticationProvider provider;

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(provider);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().antMatchers("/admin/admins**").hasAnyRole("SADMIN").antMatchers("/admin/**")
                    .hasAnyRole("ADMIN", "SADMIN", "WADMIN").antMatchers("/rest/**")
                    .hasAnyRole("ADMIN", "SADMIN", "WADMIN", "USER").antMatchers("/user/**").hasAnyRole("USER")
                    .anyRequest().permitAll().and().formLogin().loginPage("/sign-in-up")
                    .loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
                    .invalidateHttpSession(false).and().csrf().disable().cors();

        }
    }

}

注意:如果我更改订单并使formLogin@订单(1)再次生效,但当然不会生效。

我也试着把它们像这样结合起来,现在两者都很好,但是如果JWT身份验证错误将返回formlogin thymeleaf错误页面,则异常处理的问题:

@Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().antMatchers("/admin/admins**").hasAnyRole("SADMIN").antMatchers("/admin/**")
                    .hasAnyRole("ADMIN", "SADMIN", "WADMIN").antMatchers("/rest/**")
                    .hasAnyRole("ADMIN", "SADMIN", "WADMIN", "USER").antMatchers("/user/**").hasAnyRole("USER")
                    .antMatchers("/api/user/authenticate").permitAll()
                    .antMatchers("/api/user/**").hasRole("USER")
                    .anyRequest().permitAll().and().formLogin().loginPage("/sign-in-up")
                    .loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
                    .invalidateHttpSession(false).and().csrf().disable().cors();
            
            http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        }

任何建议,使这项工作。非常感谢。

共有1个答案

常英资
2023-03-14

您的WebSecurityConfigrerAdapters将按顺序处理传入的请求。
由于JWTSecurityConfig带有@order(1)注释,因此它将首先处理请求。

您尚未为此适配器指定antMatcher,因此它将匹配所有请求
这意味着请求永远不会到达FormLoginConfigurationAdapter,因为JWTSecurityConfig与它们都匹配。

如果希望JWTSecurityConfig仅应用于某些请求,可以在安全配置中指定antMatcher
下面是一个示例:

@EnableWebSecurity
public class SecurityConfigurations {

    @Configuration
    @Order(1)
    public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
           http
              .requestMatchers(matchers -> matchers
                  .antMatchers("/api/**") // apply JWTSecurityConfig to requests matching "/api/**"
              )
              .authorizeRequests(authz -> authz
                  .anyRequest().authenticated()
              )
              .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }

    @Configuration
    public class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
           http
              .authorizeRequests(authz -> authz
                  .anyRequest().authenticated()
              )
              .formLogin();
        }
    }
}

有关多个Web安全配置适配器的更多详细信息,请参阅Spring Security参考文档中的多个HttpSecurity部分。

有关authorizeRequests()requestMatchers()之间区别的更多详细信息,您可以看到这个堆栈溢出问题。

 类似资料:
  • 在控制台中写入函数:anonymousUser true[ROLE_ANONYMOUS] 并且应该是user1 true[ROLE_USER]user1

  • 我正在开发一个具有自己的身份验证和授权机制的REST应用程序。我想使用JSON Web Tokens进行身份验证。以下是有效且安全的实现吗? < li >将开发一个REST API来接受用户名和密码并进行认证。要使用的HTTP方法是POST,因此没有缓存。此外,在传输时还会有安全SSL < li >在认证时,将创建两个JWTs访问令牌和刷新令牌。刷新令牌将具有更长的有效期。这两个令牌都将写入coo

  • 我有几个angular应用程序(在不同的子域中)和一个主angular应用程序(在主域中)。我使用@auth0/Angular2-jwt库来管理身份验证。它工作得很好,但对单点登录不起作用。我必须在每个子域登录,我需要这只做一次(在主域或任何子域)。 我尝试过为whitelistedDomains使用正则表达式,但它不起作用: 那么,如果用户登录到主域或任何子域,我如何对所有子域的用户进行身份验证

  • 是否可以在ASP中支持多个JWT令牌发行者。净核心2?我想为外部服务提供一个API,我需要使用两个JWT代币来源——Firebase和定制JWT代币发行人。在ASP。NET core I可以为承载身份验证方案设置JWT身份验证,但只能为一个机构设置: 我可以有多个发行人和受众,但我不能设置多个权限。

  • 我所期望的是:当用户从表单登录时,它可以调用restful服务,而无需经过基本身份验证(因为它已经经过身份验证)。我的想法是,角色为'role_user'的用户也应该调用restful服务。但是,当我从表单登录后,我也被提示进行基本身份验证,试图从浏览器调用restful服务。 有没有得到我所期望的?

  • 在auth-routes示例中,api和nuxt一起启动并使用一个Node.js服务器实例。但是,有时我们应该使用jsonWebToken处理外部api身份验证问题。在这个例子中,将用最简单的方式解释。 官方 auth-module 如果要实现复杂的身份验证流程,例如OAuth2,我们建议使用官方 auth-module 结构 由于Nuxt.js同时提供服务器和客户端呈现,并且浏览器的cookie