簡體   English   中英

jwt 秘密的@Value 在 Spring 安全中無法正常工作

[英]@Value for jwt secret not working properly in Spring Security

我正在嘗試將 jwt 用於我的 spring 引導項目並進行 Spring 安全設置。 當我使用這個內部過濾器時

@Slf4j
@RequiredArgsConstructor
public class CustomAuthorizationFilter extends OncePerRequestFilter {

    private final JwtProvider jwtProvider;
    private final String tokenPrefix = "Bearer ";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        log.info("INITIALIZE | CustomAuthorizationFilter | doFilterInternal | " + request.getRequestURI());
        LocalDateTime initTime = LocalDateTime.now();

        String token = request.getHeader(AUTHORIZATION);
        if (token != null && token.startsWith(tokenPrefix)) {
            jwtProvider.verifyJwt(token);
        } else {
            filterChain.doFilter(request, response);
        }

        log.info("COMPLETE | CustomAuthorizationFilter | doFilterInternal | " +
                Duration.between(initTime, LocalDateTime.now()) + " | " + request.getRequestURI());
    }
}

問題:在我的 verifyJwt 中,由於某種原因,它讀取如下聲明為null的秘密。

@Value("${jwt.secret}")
private String secret;

這是我的 verifyJwt 方法

    public User verifyJwt(String token) {
        log.info("INITIALIZE | JwtProvider | verifyJwt | " + token);
        LocalDateTime initTime = LocalDateTime.now();

        if (token == null || !token.startsWith(tokenPrefix)) {
            throw new UnauthorizedException();
        }
        token = token.substring(tokenPrefix.length());
        Algorithm algorithm = Algorithm.HMAC256(secret.getBytes(StandardCharsets.UTF_8));
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT decodedJWT = verifier.verify(token);
        String username = decodedJWT.getSubject();
        String[] roles = decodedJWT.getClaim("roles").asArray(String.class);

        Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
        stream(roles).forEach(role -> {
            authorities.add(new SimpleGrantedAuthority(role));
        });

        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(username, null, authorities);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        log.info("COMPLETE | JwtProvider | verifyJwt | " + Duration.between(initTime, LocalDateTime.now()) + " | " +
                username);
        return (User) userDetailsService.loadUserByUsername(username);
    }

@Value 顯然不起作用,但它對其他方法工作正常。

任何人都有解決此問題的解決方案,除了像這樣聲明它private String secret = "secret"

這是我的 SpringSecurityConfiguration

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final UserDetailsService userDetailsService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        JwtProvider jwtProvider = new JwtProvider(userDetailsService);

        http
                .csrf().disable()
                .cors()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/contact/**",
                        "/user/duplicate/**",
                        "/user/new/**",
                        "/user/login/**",
                        "/user/auth/**",
                        "/user/findId/**",
                        "/user/findPw/**/**",
                        "/swagger-ui/index.html/**")
                .permitAll()
                .antMatchers("/user", "/user/**",
                        "/profile/**")
                .authenticated()
                .and()
                .addFilterBefore(new CustomAuthorizationFilter(jwtProvider),
                        UsernamePasswordAuthenticationFilter.class);
    }
}

將您的CustomAuthorizationFilter注冊為 spring bean 組件。

@Slf4j
@RequiredArgsConstructor
@Component // <-----------------
public class CustomAuthorizationFilter extends OncePerRequestFilter {
  ....
}

然后注冊您的自定義過濾器,以便在UsernamePasswordAuthenticationFilter之前使用

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

 @Autowired
 private JwtRequestFilter jwtRequestFilter;

 @Override
    protected void configure(HttpSecurity httpSecurity) {   
      // Add a filter to validate the tokens with every request
      httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);   
  }   
}

這樣,您的過濾器將以正確的順序被調用,並且還將被注冊為 spring bean,以便它可以訪問應用程序上下文,其中@Value將能夠訪問 function。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM