Spring Boot 配置问题中的 JWT 令牌

Posted

技术标签:

【中文标题】Spring Boot 配置问题中的 JWT 令牌【英文标题】:JWT token in Spring Boot configuration problem 【发布时间】:2020-03-01 19:13:59 【问题描述】:

我在调用发布请求时遇到问题:localhost:8080/authenticate 我的应用程序的安全性表明它需要和令牌。当请求被调用时,过滤器会检查它,所以这不是本意。现在安全要求一个不记名令牌,而这是第一个请求,当然它还不存在。我收到错误JWT Token does not begin with Bearer String

我的配置方法:

@Override
    protected void configure(WebSecurity web) throws Exception 
        web.ignoring().antMatchers("/authenticate");
    

@Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .csrf().disable()
                .cors().disable()
                .authorizeRequests()
                .antMatchers("/authenticate").permitAll()
                .antMatchers("/**/private/**").authenticated()
                .anyRequest().permitAll()
                .and()
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
    

我的过滤方法:

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException 

        final String requestTokenHeader = request.getHeader("Authorization");
        System.out.println("JWT Request: " + request.getRequestURI());
        System.out.println("JWT Contain: " + request.getRequestURI().contains("authenticate"));
        String username = null;
        String jwtToken = null;
        //Remove comment for second approach
        if (request.getRequestURI().contains("authenticate") == false) 
            System.out.println("Do Noting, Permit It");
            chain.doFilter(request, response);
         else if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) 
            jwtToken = requestTokenHeader.substring(7);
            try 
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
             catch (IllegalArgumentException e) 
                System.out.println("Unable to get JWT Token");
             catch (ExpiredJwtException e) 
                System.out.println("JWT Token has expired");
            
         else 
            logger.warn("JWT Token does not begin with Bearer String");
        

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) 

            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) 

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            
        
        chain.doFilter(request, response);
    

我的控制器类:

@RestController
@CrossOrigin
public class JwtAuthenticationController 

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private JwtUserDetailsService userDetailsService;

    @RequestMapping(value = "/authenticate", method = RequestMethod.POST)
    public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest) throws Exception 

        authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());

        final UserDetails userDetails = userDetailsService
                .loadUserByUsername(authenticationRequest.getUsername());

        final String token = jwtTokenUtil.generateToken(userDetails);

        return ResponseEntity.ok(new JwtResponse(token));
    

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public ResponseEntity<?> saveUser(@RequestBody UserDTO user) throws Exception 
        return ResponseEntity.ok(userDetailsService.save(user));
    

    private void authenticate(String username, String password) throws Exception 
        try 
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
         catch (DisabledException e) 
            throw new Exception("USER_DISABLED", e);
         catch (BadCredentialsException e) 
            throw new Exception("INVALID_CREDENTIALS", e);
        
    

我希望程序正常工作,这样当我发送localhost:8080/authenticate 请求时将没有过滤器,但是当我调用所有其他请求时,会有过滤器来检查令牌是否存在。

提前谢谢你。

【问题讨论】:

试试这个http .csrf().disable() .cors().disable() .authorizeRequests() .antMatchers("/authenticate").permitAll() .anyRequest().authenticated() .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class) 【参考方案1】:

重写configure(WebSecurity web)方法以忽略/authenticate端点,这样它就不会被包含在Spring Security Filter Chain中,如下所示;

public void configure(WebSecurity web) throws Exception 
    web.ignoring().antMatchers("/authenticate");                

【讨论】:

我已经编辑了我的问题,我已经添加了覆盖方法,但它说它需要公开? @TomvandenBogaart 将其公开。

以上是关于Spring Boot 配置问题中的 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

使用 Stomp 在 Spring Boot 中访问 JWT 令牌

jwt访问令牌存储在spring boot中的哪里?

Spring Boot OAuth2 手动创建新的 JWT 令牌

Spring Boot + Security + JWT 无法生成令牌

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

我已经在 Spring Boot 代码中实现了 JWT 令牌安全性。如何在我的代码中的任何地方获取 jwt 令牌?需要保存审核