多个 WebSecurityConfigurerAdapters:Spring Security 中的 JWT 身份验证和表单登录 [英] Multiple WebSecurityConfigurerAdapters: JWT authentication and form login in spring security

查看:46
本文介绍了多个 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 可以正常工作,但表单登录已停止并调用/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.

您尚未为此适配器指定 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的更多细节,你可以查看Spring Security 参考文档中的多个 HttpSecurity 部分.

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

更多关于authorizeRequests()requestMatchers()的区别,可以看这个堆栈溢出问题.

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

这篇关于多个 WebSecurityConfigurerAdapters:Spring Security 中的 JWT 身份验证和表单登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆