在 Spring Boot 中成功身份验证后未生成 JWT 令牌

Posted

技术标签:

【中文标题】在 Spring Boot 中成功身份验证后未生成 JWT 令牌【英文标题】:JWT Token not generated after successful Authentication in Spring Boot 【发布时间】:2020-10-24 14:11:03 【问题描述】:

我为每个请求创建了两个过滤器来运行 JwtUsernameAndPasswordFilter 和 JwtTokenVerifier。我以前使用过这两个过滤器,它们已经奏效了。我认为主要问题在于我的 Spring Security Config。当我调试这两个过滤器时,只有 JwtTokenVerified 被识别并且 JwtUsernameAndPasswordFilter 根本不会被调用。当我使用 application/json 内容类型从 PostMan 发出请求时,服务器会给我一个错误:

class path resource [templates/logIn.html] cannot be opened because it does not exist

/登录控制器

@RequestMapping(value="/logIn",method = RequestMethod.POST,RequestMethod.GET)
    public void login()
    

Spring 安全配置

@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@Configuration
@Builder
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    private SecureUserDaoService secureUserDaoService;
    private JwtConfig jwtConfig;
    private SecretKey secretKey;
    private PasswordEncoder passwordEncoder;


    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .csrf().disable()

                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and()

                .addFilter(new JwtUsernameAndPasswordFilter(authenticationManager(), jwtConfig, secretKey))
                .addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig), JwtUsernameAndPasswordFilter.class)

                .authorizeRequests()

                .antMatchers("/accountPage", "/accountSettings").authenticated()
                .antMatchers("/", "/signUp", "/logIn").permitAll()
                .anyRequest().authenticated()
                .and()

                .formLogin()
                .failureUrl("/")
                .successForwardUrl("/accountPage");
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.authenticationProvider(daoAuthenticationProvider());
    

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider()
        DaoAuthenticationProvider provider =
                new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder);
        provider.setUserDetailsService(secureUserDaoService);
        return provider;
    

githubrepo

更新:

通过在客户端调用“/login”而不是“/logIn”使其工作,因为显然即使我添加了 .loginPage("/logIn") AND .logInProcessingUrl("/logIn")。看起来像春天通过过滤器链时仍然无法识别我的自定义登录控制器。如果您知道更好的解决方案,请随时在下面发表评论

【问题讨论】:

好的,所以我在 formLogIn 设置中添加了一个 .loginPage("/logIn") 但是当我使用请求标头 Content-Type: application/json 发出请求并将用户名和密码参数存储在正文为 JSON。它给了我一个找不到用户的错误,因为 DaoAuthenticationProvider.class 中的 retreiveUser() 方法没有给出用户名参数。当我再次检查错误堆栈时,我发现未调用 UsernameAndPassword 过滤器 @KavithakaranKanapathippillai 我编辑了我的帖子并找到了某种解决方案。虽然它不是我想要找到的那种。 【参考方案1】:

当我调试这两个过滤器时,只有 JwtTokenVerified 被识别并且 JwtUsernameAndPasswordFilter 根本没有被调用。

JwtUsernameAndPasswordFilter 正在被调用。为了证明这一点,要么在您的过滤器中添加一个调试语句,或者更好地在您的SecurityConfig.java 中启用Spring Security debugger,如下所示:

@EnableWebSecurity(debug=true)

你会看到这个:

Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  LogoutFilter
  JwtUsernameAndPasswordFilter            // This is your filter
  UsernamePasswordAuthenticationFilter
  JwtTokenVerifier                        // This is your filter
  DefaultLoginPageGeneratingFilter
  DefaultLogoutPageGeneratingFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]

当我使用应用程序/json 内容从 PostMan 发出请求时 键入服务器会给我一个错误:

类路径资源 [templates/logIn.html] 无法打开,因为它 不存在

这是因为在您的/templates 文件夹中,没有logIn.html

通过在客户端调用“/login”而不是“/logIn”使其工作, 因为显然即使我添加 .loginPage("/logIn") AND .logInProcessingUrl("/logIn"). 好像spring还是没有 通过过滤器时识别我的自定义登录控制器 链。如果您知道更好的解决方案,请随时在下面发表评论

/login 之所以有效,是因为您没有在 SecurityConfig.java 中定义自定义登录页面,Spring Security 会将您重定向到其默认登录页面。

如果您不想要该功能,您可以自定义loginPage,如下所示:

.and()
.formLogin().loginPage("/customizeMe")   // Your custom login page here
.failureUrl("/")
.successForwardUrl("/accountPage");

【讨论】:

以上是关于在 Spring Boot 中成功身份验证后未生成 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

Django-为啥内置身份验证登录功能在成功登录网址后未将有关用户的信息传递给

IBM Worklight:基于适配器的身份验证成功后未获得响应

Spring Boot with Spring Boot:将基本身份验证与JWT令牌身份验证相结合[复制]

Spring Boot 配置 + RepositoryRestResource + 身份验证

spring boot spring security 基于自定义令牌的身份验证和自定义授权

spring boot 项目登录模块之身份验证