我在另一台计算机上使用了SpringBoot应用程序,我从GitHub克隆了该项目并设置了我的IntelliJ,安装了所有依赖项并try 运行该程序.

我注意到的第一件事是绕过了安全配置.尽管我已准备好配置文件,但仍会为我生成密码.当我打开localhost:8080并登录时,所有端点也不工作.

所有这些都能在我以前的电脑上用相同版本的IntelliJ运行.

  • 我试过使用@ComponentScan,但仍然得到相同的结果.
  • I have added this line to my Application.properties logging.level.org.springframework.web=TRACE and it only shows that one endpoint is avalible, "/error"

这是我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.appholdings</groupId>
    <artifactId>appname</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>appname</name>
    <description>appname</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.11.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.11.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.11.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <version>3.0.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.0.5</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.24</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk</artifactId>
            <version>1.12.429</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.asciidoctor</groupId>
                <artifactId>asciidoctor-maven-plugin</artifactId>
                <version>2.2.1</version>
                <executions>
                    <execution>
                        <id>generate-docs</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>process-asciidoc</goal>
                        </goals>
                        <configuration>
                            <backend>html</backend>
                            <doctype>book</doctype>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.restdocs</groupId>
                        <artifactId>spring-restdocs-asciidoctor</artifactId>
                        <version>${spring-restdocs.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>testCompile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

安全配置

package com.mootoholdings.ecommserver.config;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http ) throws Exception {
        http.cors().and()
                .authorizeHttpRequests(request -> request
                        .requestMatchers("/api/v1/auth/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/products/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/categories", "/api/categories/*").permitAll()
                        .requestMatchers(HttpMethod.GET, "/").permitAll()
//                        .anyRequest().authenticated()
                                .anyRequest().permitAll()
                )
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .csrf().disable();

        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("*"));
        configuration.setAllowedMethods(List.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));
        // setAllowCredentials(true) is important, otherwise:
        // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
        configuration.setAllowCredentials(false);
        // setAllowedHeaders is important! Without it, OPTIONS preflight request
        // will fail with 403 Invalid CORS request
        configuration.setAllowedHeaders(List.of("*"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

身份验证过滤器

import com.mootoholdings.ecommserver.service.JWTService;

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JWTService jwtService;
    private final UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(
            @NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain
    ) throws ServletException, IOException {

        final String authHeader = request.getHeader("Authorization");
        final String jwt;
        final String userEmail;

        if (authHeader == null || !authHeader.startsWith("Bearer")){
            filterChain.doFilter(request, response);
            return;
        }

        jwt = authHeader.substring(7);

        userEmail = jwtService.decodeUsername(jwt);

        if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null){
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
            if(jwtService.isTokenValid(jwt, userDetails)){
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );
                authToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }
         try {
            // something may throw an exception
            filterChain.doFilter(request, response);
         } catch (ServletException | IOException e) {
             log.error(e.getMessage());
         }
    }

}

我的应用程序入口点

package com.mootoholdings.ecommserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class EcommserverApplication {
    public static void main(String[] args) {
        SpringApplication.run(EcommserverApplication.class, args);
    }
}

JWT服务

package com.mootoholdings.ecommserver.service;

@Slf4j
@Service
public class JWTService {
    private final SupplierRepository supplierRepository;

    private final UserRepository userRepository;
    private final RiderRepository riderRepository;
    private final AdminRepository adminRepository;
    private final DistributorRepository distributorRepository;

    public JWTService(UserRepository userRepository,
                      RiderRepository riderRepository,
                      AdminRepository adminRepository,
                      DistributorRepository distributorRepository,
                      SupplierRepository supplierRepository) {
        this.userRepository = userRepository;
        this.riderRepository = riderRepository;
        this.adminRepository = adminRepository;
        this.distributorRepository = distributorRepository;

        this.supplierRepository = supplierRepository;
    }

    @Value("${SECRET_KEY}")
    private String SECRET_KEY;

    // Extracts Username
    public String decodeUsername(String token){
        return extractClaim(token, Claims::getSubject);
    }

    public String decodeUserId(String token){
        return extractClaim(token, Claims::getId);
    }

    public String extractFirstRole(String token) {
        List<SimpleGrantedAuthority> rolesClaim = extractClaim(token, claims ->
                ((List<?>) claims.get("roles")).stream()
                        .map(authority -> new SimpleGrantedAuthority(authority.toString()))
                        .collect(Collectors.toList())
        );
        if (!rolesClaim.isEmpty()) {
            String roleString = rolesClaim.get(0).getAuthority().split("=")[1];
            return roleString.substring(0, roleString.length() - 1);
        } else {
            return null;
        }
    }


    // Extract claims from token
    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver){
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }

    // Makes new token
    public String genToken(UserDetails userDetails, String role){
        return generateToken(new HashMap<>(), userDetails, role);
    }

    // Makes new token
    public String generateToken(
            Map<String, Object> extraClaims,
            UserDetails userDetails,
            String role
    ){
        if (Objects.equals(role, "DISTRIBUTOR")){
            log.info("In distributor");
            Distributor distributor = distributorRepository.findDistributorByEmail(userDetails.getUsername());
            return getJwt(extraClaims, userDetails, distributor.getId(), distributor.getFirstName(), distributor.getLastName());
        }
        else if (Objects.equals(role, "SUPPLIER")){
            log.info("In supplier");
            Supplier supplier = supplierRepository.findSupplierByEmail(userDetails.getUsername());
            log.info("attempting get JWT");
            return getJwt(extraClaims, userDetails, supplier.getId(), supplier.getFirstName(), supplier.getLastName());
        }
        else if (Objects.equals(role, "RIDER")){
            log.info("In rider");
            Rider rider = riderRepository.findRiderByEmail(userDetails.getUsername());
            log.info("attempting get JWT");
            return getJwt(extraClaims, userDetails, rider.getId(), rider.getFirstName(), rider.getLastName());
        }
        else if (Objects.equals(role, "ADMIN")){
            log.info("In admin");
            Admin admin = adminRepository.findAdminByEmail(userDetails.getUsername());
            return getJwt(extraClaims, userDetails, admin.getId(), admin.getFirstName(), admin.getLastName());
        }
        else {
            log.info("In User");
            User user = userRepository.findUserByEmail(userDetails.getUsername());
            return getJwt(extraClaims, userDetails, user.getId(), user.getFirstName(), user.getLastName());
        }


    }

    private String getJwt(Map<String, Object> extraClaims, UserDetails userDetails, long id, String firstName, String lastName) {
        return Jwts.builder()
                .setClaims(extraClaims)
                .setSubject(userDetails.getUsername())
                .claim ("id", id)
                .claim("firstName", firstName)
                .claim("lastName", lastName)
                .claim("roles", userDetails.getAuthorities())
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 5))
                .signWith(getSignInKey(), Signature算法rithm.HS256)
                .compact();
    }

    // Validate token
    public boolean isTokenValid(String token, UserDetails userDetails){
        final String username = decodeUsername(token);
        return (username.equals(userDetails.getUsername())) && !isTokenExpired(token);
    }

    private boolean isTokenExpired(String token){
        return extractExpiration(token).before(new Date());
    }

    private Date extractExpiration(String token){
        return extractClaim(token, Claims::getExpiration);
    }

    private Claims extractAllClaims (String token){
        return Jwts
                .parserBuilder()
                .setSigningKey(getSignInKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    private Key getSignInKey() {
        byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
        return Keys.hmacShaKeyFor(keyBytes);
    }
}

Application.properties

 spring.datasource.url=jdbc:mysql://localhost:3306/ecommdb?sessionVariables=sql_mode='NO_ENGINE_SUBSTITUTION'&jdbcCompliantTruncation=false
 spring.datasource.username=user
 spring.datasource.password=user
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true

logging.level.org.springframework.web=TRACE

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true

spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=2KB
spring.servlet.multipart.max-file-size=200MB
spring.servlet.multipart.max-request-size=215MB

应用程序配置

package com.mootoholdings.ecommserver.config;


@Slf4j
@Configuration
public class ApplicationConfig {

    private final UserRepository userRepository;
    private final AdminRepository adminRepository;
    private final RiderRepository riderRepository;
    private final DistributorRepository distributorRepository;
    private final SupplierRepository supplierRepository;

    public ApplicationConfig(UserRepository userRepository, AdminRepository adminRepository,
            RiderRepository riderRepository, DistributorRepository distributorRepository,
            SupplierRepository supplierRepository) {
        this.userRepository = userRepository;
        this.adminRepository = adminRepository;
        this.riderRepository = riderRepository;
        this.distributorRepository = distributorRepository;
        this.supplierRepository = supplierRepository;
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return username -> {
            Optional<Rider> rider = riderRepository.findByEmail(username);
            if (rider.isPresent()) {
                log.info("authenticating rider");
                return new org.springframework.security.core.userdetails.User(rider.get().getEmail(),
                        rider.get().getPassword(), new ArrayList<>());
            }
            Optional<User> user = userRepository.findByEmail(username);
            if (user.isPresent()) {
                log.info("authenticating user");
                return new org.springframework.security.core.userdetails.User(user.get().getEmail(),
                        user.get().getPassword(), new ArrayList<>());
            }
            Optional<Admin> admin = adminRepository.findByEmail(username);
            if (admin.isPresent()) {
                log.info("authenticating admin");
                return new org.springframework.security.core.userdetails.User(admin.get().getEmail(),
                        admin.get().getPassword(), new ArrayList<>());
            }
            Optional<Distributor> distributor = distributorRepository.findByEmail(username);
            if (distributor.isPresent()) {
                log.info("authenticating dist");
                return new org.springframework.security.core.userdetails.User(distributor.get().getEmail(),
                        distributor.get().getPassword(), new ArrayList<>());
            }
            Optional<Supplier> supplier = supplierRepository.findByEmail(username);
            if (supplier.isPresent()) {
                log.info("authenticating supplier");
                return new org.springframework.security.core.userdetails.User(supplier.get().getEmail(),
                        supplier.get().getPassword(), new ArrayList<>());
            }
            throw new UsernameNotFoundException("User not found");
        };
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

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

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

}

folder structure FolderStructure

我能做错什么呢?

UPDATE:包含的包名. UPDATE:在GitHub代码空间上运行它,它工作正常,所以我猜它与我的机器设置有关

推荐答案

做了一个完整的调试,归根结底是笔记本电脑的名字.原始名称中有一个空格,因此当它开始搜索项目中的存储库时,它会失败并取消搜索.为了解决这个问题,我刚刚创建了另一个帐户,并将项目移动到公用文件夹,因为我无法更改笔记本电脑的名称,现在一切都很好.

Java相关问答推荐

为什么我们仍然需要实现noArgsConstructor如果Java默认提供一个非参数化的构造函数?''

ittext pdf延迟签名,签名无效

JVM会优化这个数学运算吗?

连接Quarkus中的两个异步操作

如何找到MongoDB文档并进行本地化?

是否在允许数组元素为空时阻止 idea 为空性警告?

名称冲突具有相同的擦除

如何在ApachePOI中将图像添加到工作表的页眉?

有没有办法让扩展变得多态?

如何在EXCEL单元格中添加形状和文本

将Spring Boot 3.2.0升级到3.2.1后查询执行错误

如何集成语义发布和BitBucket(Java项目)

在向WebSphere中的文档添加元素时iText挂起

try 使用Spring集成和MySQL实现发件箱模式时,锁定等待超时

组合连接以从两个表返回数据

无法使用Open WebStart Java 8运行jnlp

Java 21内置http客户端固定运营商线程

如何在MPAndroidChart中的条形图上正确添加标签

转换为JSON字符串时,日期按天递减-Java

SonarQube在合并升级到java17后对旧代码提出错误