简体   繁体   English

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

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

I am trying to use jwt for my spring boot project and have Spring Security setup.我正在尝试将 jwt 用于我的 spring 引导项目并进行 Spring 安全设置。 When I use the Internal filter which is this当我使用这个内部过滤器时

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

Problem : In my verifyJwt, it reads the secret which is declared as below as null for some reason.问题:在我的 verifyJwt 中,由于某种原因,它读取如下声明为null的秘密。

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

And this is my verifyJwt method这是我的 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);
    }

The @Value is not working obviously, but it is working fine for other methods. @Value 显然不起作用,但它对其他方法工作正常。

Anyone has a solution to fix this problem except for declaring it like this private String secret = "secret"任何人都有解决此问题的解决方案,除了像这样声明它private String secret = "secret"

This is my SpringSecurityConfiguration这是我的 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);
    }
}

Register your CustomAuthorizationFilter as a spring bean component.将您的CustomAuthorizationFilter注册为 spring bean 组件。

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

Then register your custom filter to be used just before UsernamePasswordAuthenticationFilter然后注册您的自定义过滤器,以便在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);   
  }   
}

This way your filter will be invoked just in the right order and also would be registered as a spring bean so that it has access to application context where @Value will be able to function.这样,您的过滤器将以正确的顺序被调用,并且还将被注册为 spring bean,以便它可以访问应用程序上下文,其中@Value将能够访问 function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM