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

c8ib6hqw  于 4个月前  发布在  Spring
关注(0)|答案(2)|浏览(52)

**已关闭。**此问题不符合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
我有这个代码:

安全过滤器

@Component
public class SecurityFilter extends OncePerRequestFilter {

    @Autowired
    TokenService token_service = new TokenService();
    @Autowired
    private UserRepository user_repository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filter_chain) throws ServletException, IOException {
        String token = getToken(request);
        if(token != null){
            String token_subject = token_service.getTokenSubject(token);
            UserDetails user_entity = user_repository.findByEmail(token_subject);
            Authentication authentication = new UsernamePasswordAuthenticationToken(user_entity, null, user_entity.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filter_chain.doFilter(request, response);
    }

    private String getToken(HttpServletRequest request){
        String token = request.getHeader("Authorization");
        if(token == null){
            return null;
        }
        return token.replace("Bearer", "");
    }

}

字符串

安全配置

@Configuration
@EnableWebSecurity
public class SecurityConfigurations {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(http_request -> http_request
                .requestMatchers("/auth/login").permitAll()
                .anyRequest().authenticated()
            )
            .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .addFilterBefore(new SecurityFilter(), UsernamePasswordAuthenticationFilter.class)
            .build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration auth_config) throws Exception {
        return auth_config.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

}

令牌配置

@Service
public class TokenService {

    private final String secret = "b0eMdsHE5jKDW9RsjuC5VrF8BT7P2oHubObbdBvaVbfzlXgKftxQ2WrZfX4RtU04";
    private final String ISSUER = "API Pacheco's School";

    public String createToken(UserEntity user){
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                    .withIssuer(ISSUER)
                    .withExpiresAt(getExpiresAt())
                    .withSubject(user.getUsername())
                    .sign(algorithm);
        } catch (JWTCreationException exception){
            return null;
        }
    }

    private Instant getExpiresAt(){
        return LocalDateTime.now().plusDays(1).toInstant(ZoneOffset.of("-03:00"));
    }

    public String getTokenSubject(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.require(algorithm)
                    .withIssuer(ISSUER)
                    .build()
                    .verify(token)
                    .getSubject();
        } catch (JWTVerificationException exception){
            return null;
        }
    }
}

用户仓库

public interface UserRepository extends JpaRepository<UserEntity, Long> {

    @Query(value = "SELECT u FROM UserEntity u WHERE " +
        "u.name LIKE CONCAT('%', :name, '%') " +
        "OR u.birth_date = :date " +
        "OR u.email LIKE CONCAT('%', :email, '%') " +
        "OR cellphone LIKE CONCAT('%', :cellphone, '%') "
    )
    Collection<UserEntity> searchUsers(String name, LocalDate date, String email, String cellphone);

    UserDetails findByEmail(String email);
}


我在安全过滤器中的令牌服务也遇到了同样的错误,但由于它是一个类,我只是用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

安全问题

@Autowired
SecurityFilter security_filter;

字符串

相关问题