首页 > 解决方案 > springboot 战争适用于嵌入式 tomcat,但不适用于外部 tomcat

问题描述

我一直在开发一个带有 spring security 的 springboot 2.3.4 应用程序。它适用于嵌入式 tomcat。我们想让它与外部应用程序服务器(如 tomcat 和 jboss)一起工作。我试图将war文件部署在外部tomcat服务器中。到达端点时,我收到 404 错误代码。这是我的pom文件:

<?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>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.teradata</groupId>
    <artifactId>modelstudio</artifactId>
    <version>1</version>
    <name>modelstudio</name>
    <packaging>war</packaging>
    <description>ModelStudio Application</description>

    <properties>
       <java.version>13</java.version>
       <start-class>
            com.teradata.modelstudio.ModelStudioApplication
       </start-class>
    </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-jdbc</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>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.skyscreamer</groupId>
                    <artifactId>jsonassert</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.teradata.jdbc</groupId>
            <artifactId>terajdbc4</artifactId>
            <version>17</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20200518</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.json</groupId>
                    <artifactId>json</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
    <finalName>modelstudio</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>static/**</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <excludes>
                    <exclude>ModelStudioUI/**</exclude>
                    <exclude>static/**</exclude>
                </excludes>
            </resource>
        </resources>
    </build>

</project>

我的 JWT 入口点是:

package com.teradata.modelstudio.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.teradata.modelstudio.service.CustomAuthenticationProviderService;
import com.teradata.modelstudio.utils.JwtUtil;
import com.teradata.modelstudio.utils.Logger;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.regex.Pattern;

@Component
public class JwtFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private CustomAuthenticationProviderService service;
    
    @Autowired JwtUserDetailsService jwtUserDetailsService;


    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        
        String requestURI = httpServletRequest.getRequestURI();
        Logger.info("==================="+requestURI);
        Pattern mega = Pattern.compile(
                "\\/*.css|\\/*.js|\\/*.png|\\/*.jpg|\\/assets\\/*.*|\\/*.woff2|\\/*.woff|\\/*.ttf|\\/swagger-resources\\/*|/servicemanagement/configuration/*|/servicemanagement/etlframework/*|/servicemanagement/refreshCache/*");

        // System.out.println(requestURI);

        if (httpServletRequest.getMethod().equals("OPTIONS")// || requestURI.equalsIgnoreCase("/index.html")
                || requestURI.equalsIgnoreCase("/favicon.ico") || mega.matcher(requestURI).find() || requestURI.equalsIgnoreCase("/")) {
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

        // TODO Auto-generated method stub
        String url = httpServletRequest.getRequestURL().toString();
//      System.out.println("+++URL in jwt request filter:"+url);
        if (url.contains("auth") || url.contains("dbcontent") || url.contains("favico")) {
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

        String requestTokenHeader = httpServletRequest.getHeader("Authorization");

        String username = null;
        String password = null;
        String serverUrl = null;
        String dbName = null;
        String authType = null;
        String jwtToken = null;

        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtUtil.getUsernameFromJWT(jwtToken);
                password = jwtUtil.getPasswordFromJWT(jwtToken);
                serverUrl = jwtUtil.getServerUrlFromJWT(jwtToken);
                dbName = jwtUtil.getDbNameFromJWT(jwtToken);
                authType = jwtUtil.getAuthTypeFromJWT(jwtToken);
                jwtUtil.validateToken(jwtToken, username);
            } catch (Exception e) {
                throw e;
            }

        } else {
            throw new IOException("Invalid Authorization");
        }
        
        
        SecurityContextHolder.getContext().setAuthentication(null);

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(username);

            if (jwtUtil.validateToken(jwtToken, username)) {
                
                CustomUserPrincipal customUserPrincipal = new CustomUserPrincipal(username, password, serverUrl, dbName, authType);

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(customUserPrincipal, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}


我的安全配置文件:

package com.teradata.modelstudio.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.teradata.modelstudio.filter.JwtFilter;
import com.teradata.modelstudio.payload.JwtAuthenticationResponse;
import com.teradata.modelstudio.security.JwtAuthenticationEntryPoint;
import com.teradata.modelstudio.service.CustomAuthenticationProviderService;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProviderService authenticationProviderService;

    @Autowired
    private JwtFilter jwtFilter;
    
    @Autowired
    JwtAuthenticationEntryPoint unauthorizedHandler;
    
    @Autowired
    private com.teradata.modelstudio.filter.SimpleCORSFilter simpleCORSFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
        .antMatchers(
                HttpMethod.GET,
              "/",
              "/*.html",
              "/*.svg",
              "/*.png",
              "/*.woff",
              "/*.woff2",
              "/*.svg",
              "/*.jpg",
              "/*.json",
              "/favicon.ico",
              "/**/*.html",
              "/**/*.css",
              "/**/*.js",
              "/**/*.svg",
              "/**/*.png",
              "/**/*.jpg",
              "/**/*.ico",
              "/**/*.icons",
              "/resources/**",
              "/assets/",
              "/static/**",
              "/h2-console/**"
        ).permitAll()
        .antMatchers("/auth/**", "/dbcontent/**")
                .permitAll()
                .anyRequest().authenticated()
                .and().exceptionHandling().and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(simpleCORSFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProviderService);
    }
    
    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

我的控制器类之一是:

package com.teradata.modelstudio.controllers;

import java.io.File;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.teradata.modelstudio.exception.ModelStudioException;
import com.teradata.modelstudio.utils.Logger;
import org.apache.commons.io.FileUtils;
import org.json.JSONObject;

@RestController
@RequestMapping("dbcontent")
public class DBContentController {
    
    @GetMapping(path="servers", produces = "application/json")
    public ResponseEntity<?> getServers() {
        try {
            String dbConFilePath = System.getProperty("user.dir")+File.separator+"db-con";
            File file = new File(dbConFilePath);
            String content = FileUtils.readFileToString(file, "utf-8");
            // Convert JSON string to JSONObject
            JSONObject fileContents = new JSONObject(content);
            return ResponseEntity.ok(fileContents.toString());
        } catch(Exception e) {
            Logger.error("Unable to get servers: "+e.getMessage());
            throw new ModelStudioException(e.getMessage());
        }
    }
    
}

这是我的主要课程

package com.teradata.modelstudio;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication(
          exclude = { DataSourceAutoConfiguration.class, 
             HibernateJpaAutoConfiguration.class,
             DataSourceTransactionManagerAutoConfiguration.class, 
             })
public class ModelstudioApplication extends SpringBootServletInitializer{

    public static void main(String[] args) {
        SpringApplication.run(ModelstudioApplication.class, args);
    }
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(ModelstudioApplication.class);
    }

}

使用嵌入式 tomcat 服务器,我点击:

本地主机:8080/dbcontent/servers

我在外部得到结果,我执行以下操作:

本地主机:8080/modelstudio/dbcontent/servers

我得到404。

谁能帮助并建议我如何使用外部服务器(如tomcat)解决此问题。

标签: javaspring-bootmaventomcat9

解决方案


推荐阅读