多个WebSecurityConfigurerAdapters:spring security中的JWT认

时间:2023-01-13
本文介绍了多个WebSecurityConfigurerAdapters:spring security中的JWT认证和表单登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有带有 thymeleaf 的 spring boot 应用程序.我正在使用 spring security formLogin 方法来保证安全,现在我只需要为一些 API 添加 JWT.

I have spring boot app with thymeleaf. I am using spring security formLogin method for security and now I need to add JWT for only some APIs.


@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();

        }
    }

}

通过执行此操作,JWT 可以正常工作,但 formlogin 已停止并调用/signInProcess".现在给404:

by doing this JWT is working fine as just I need but the formlogin has stopped and calling "/signInProcess" now give 404:

注意:如果我更改顺序并设置 formLogin @order(1) 它会再次工作,但当然不会工作.

NOTE: if I change the order and make formLogin @order(1) it works again but of course will not work.

我也尝试像这样将它们结合起来,现在它们都可以正常工作,但是如果 JWT 身份验证错误将返回 formlogin thymeleaf 错误页面,则会出现异常处理问题:

Also I tried to combine them both like this now it is both works fine but the problem with exception handling if the JWT authentication error will return formlogin thymeleaf error page :

@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);

        }

任何建议使这项工作.谢谢.

any suggestions to make this work. thank you.

推荐答案

您的 WebSecurityConfigurerAdapters 将按顺序处理传入的请求.
由于 JWTSecurityConfig 带有 @Order(1) 注释,它会首先处理请求.

Your WebSecurityConfigurerAdapters will process the incoming requests in order.
Since JWTSecurityConfig is annotated with @Order(1) it will process the requests first.

你没有为这个Adapter指定一个antMatcher,所以它会匹配所有的请求.
这意味着请求永远不会到达 FormLoginConfigurationAdapter,因为 JWTSecurityConfig 匹配所有这些.

You have not specified a antMatcher for this Adapter, so it will match all requests.
This means that a request will never reach FormLoginConfigurationAdapter, since JWTSecurityConfig matches them all.

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

If you want JWTSecurityConfig to only apply to certain requests, you can specify an antMatcher in your security configuration.
Below is an example:

@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();
        }
    }
}

关于多个WebSecurityConfigurerAdapter的更多细节,可以查看multiple HttpSecurity 部分.

For more details on multiple WebSecurityConfigurerAdapter, you can see the multiple HttpSecurity section in the Spring Security reference docs.

authorizeRequests()requestMatchers() 的更多区别可以看这个 Stack Overflow 问题.

For more details on the difference between authorizeRequests() and requestMatchers(), you can see this Stack Overflow question.

这篇关于多个WebSecurityConfigurerAdapters:spring security中的JWT认证和表单登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

上一篇:如何让 @WebMvcTest 与 OAuth 一起使用? 下一篇:将 jhipster 后端和前端分成两个项目?

相关文章

最新文章