spring 无法调用“UserRepository.findByEmail(String)”,因为“this.user_repository”为null [已关闭]

c8ib6hqw  于 2024-01-05  发布在  Spring
关注(0)|答案(2)|浏览(113)

**已关闭。**此问题不符合Stack Overflow guidelines。目前不接受回答。

这个问题似乎与help center中定义的范围内的编程无关。
21天前关闭
Improve this question
我正在创建一个Java API,在安全过滤器中收到此错误:
java.lang.NullPointerException:无法调用“school.pachecos. API.users.UserRepository.findByEmail(String)”,因为“this.user_repository”为null
我有这个代码:

安全过滤器

  1. @Component
  2. public class SecurityFilter extends OncePerRequestFilter {
  3. @Autowired
  4. TokenService token_service = new TokenService();
  5. @Autowired
  6. private UserRepository user_repository;
  7. @Override
  8. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filter_chain) throws ServletException, IOException {
  9. String token = getToken(request);
  10. if(token != null){
  11. String token_subject = token_service.getTokenSubject(token);
  12. UserDetails user_entity = user_repository.findByEmail(token_subject);
  13. Authentication authentication = new UsernamePasswordAuthenticationToken(user_entity, null, user_entity.getAuthorities());
  14. SecurityContextHolder.getContext().setAuthentication(authentication);
  15. }
  16. filter_chain.doFilter(request, response);
  17. }
  18. private String getToken(HttpServletRequest request){
  19. String token = request.getHeader("Authorization");
  20. if(token == null){
  21. return null;
  22. }
  23. return token.replace("Bearer", "");
  24. }
  25. }

字符串

安全配置

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfigurations {
  4. @Bean
  5. public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  6. return http
  7. .csrf(csrf -> csrf.disable())
  8. .authorizeHttpRequests(http_request -> http_request
  9. .requestMatchers("/auth/login").permitAll()
  10. .anyRequest().authenticated()
  11. )
  12. .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  13. .addFilterBefore(new SecurityFilter(), UsernamePasswordAuthenticationFilter.class)
  14. .build();
  15. }
  16. @Bean
  17. public AuthenticationManager authenticationManager(AuthenticationConfiguration auth_config) throws Exception {
  18. return auth_config.getAuthenticationManager();
  19. }
  20. @Bean
  21. public PasswordEncoder passwordEncoder(){
  22. return new BCryptPasswordEncoder();
  23. }
  24. }

令牌配置

  1. @Service
  2. public class TokenService {
  3. private final String secret = "b0eMdsHE5jKDW9RsjuC5VrF8BT7P2oHubObbdBvaVbfzlXgKftxQ2WrZfX4RtU04";
  4. private final String ISSUER = "API Pacheco's School";
  5. public String createToken(UserEntity user){
  6. try {
  7. Algorithm algorithm = Algorithm.HMAC256(secret);
  8. return JWT.create()
  9. .withIssuer(ISSUER)
  10. .withExpiresAt(getExpiresAt())
  11. .withSubject(user.getUsername())
  12. .sign(algorithm);
  13. } catch (JWTCreationException exception){
  14. return null;
  15. }
  16. }
  17. private Instant getExpiresAt(){
  18. return LocalDateTime.now().plusDays(1).toInstant(ZoneOffset.of("-03:00"));
  19. }
  20. public String getTokenSubject(String token){
  21. try {
  22. Algorithm algorithm = Algorithm.HMAC256(secret);
  23. return JWT.require(algorithm)
  24. .withIssuer(ISSUER)
  25. .build()
  26. .verify(token)
  27. .getSubject();
  28. } catch (JWTVerificationException exception){
  29. return null;
  30. }
  31. }
  32. }

用户仓库

  1. public interface UserRepository extends JpaRepository<UserEntity, Long> {
  2. @Query(value = "SELECT u FROM UserEntity u WHERE " +
  3. "u.name LIKE CONCAT('%', :name, '%') " +
  4. "OR u.birth_date = :date " +
  5. "OR u.email LIKE CONCAT('%', :email, '%') " +
  6. "OR cellphone LIKE CONCAT('%', :cellphone, '%') "
  7. )
  8. Collection<UserEntity> searchUsers(String name, LocalDate date, String email, String cellphone);
  9. UserDetails findByEmail(String email);
  10. }


我在安全过滤器中的令牌服务也遇到了同样的错误,但由于它是一个类,我只是用new创建了它,但我不能用user_repository来创建它。

q7solyqu

q7solyqu1#

这段代码中有几个错误,我将指出它们。
首先,我要指出最大的问题,(spring security)内置了很多预构建的安全标准。Basic login *,FormLoginOauth2SAMLmTLS 等。但是你选择忽略所有这些预构建的标准,并决定构建某种自定义的安全解决方案,直接向浏览器分发JWT,并将其用作会话。
您构建的这种类型的身份验证有点类似于Oauth2 rfc6749定义的 Resource Owner Password Credentials Grantimplicit grant

这两种身份验证类型都被视为“不得使用”或“不应使用”,因为已发现与它们相关的多个严重漏洞。

因此,这里的重点是,这种类型的身份验证不应该在2023年之前内置到新系统中。
现在来看看代码中更多的技术问题。
您已经注解了自定义过滤器@Component,这意味着当服务器启动并扫描文件树中主类下面的所有类时,这个类将被spring上下文拾取并添加为Bean
只有 spring beans 可以使用Autowire annotation,因为如果不是spring示例化了你的类,spring怎么知道要自动连接到哪个类?
然后你也会调用new SecurityFilter(),这意味着你正在手动示例化这个类,所以spring完全不知道这个类是什么,并且ofc你的autowired字段将返回null。
你得选一个

  • 你可以让Spring管理你的Bean(推荐)。
  • 示例化类并通过构造函数提供类。

这是基本的 Spring Bean 知识,我建议你读了基础知识。
如前所述,应该删除整个安全实现。JWT不应该用作会话。
https://developer.okta.com/blog/2017/08/17/why-jwts-suck-as-session-tokens
https://redis.com/blog/json-web-tokens-jwt-are-dangerous-for-user-sessions/
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/
可悲的是,有太多的博主在那里写教程,制作youtube视频,他们不知道真实的安全是如何工作的,甚至从来没有读过spring安全文档。
Springs own recommendations for implementing SPA applications

展开查看全部
ybzsozfc

ybzsozfc2#

我找到了解决办法
我已经在spring安全函数中初始化了new SecurityFilter()
.addFilterBefore(new SecurityFilter(), UsernamePasswordAuthenticationFilter.class)
我应该把它写成@Autowired

安全问题

  1. @Autowired
  2. SecurityFilter security_filter;

字符串

相关问题