我正在使用Spring Boot& amp;使用JWT身份验证进行反应。我在开发过程中使用了spring-boot-starter-tomcat中的嵌入式Tomcat,并配置了&成功测试了我的API的每个处理程序/方法。
然后我打包并将应用程序作为WAR部署到应用程序服务器/ servlet容器等。应用程序开始拒绝来自我的客户端和Firefox上的其余客户端“RESTClient”的authenticated()请求。我通过我的JwtFilter监控了请求,这不是错误的凭据。
我尝试过使用Glassfish 4.1.2(build 1)中的其他端点而没有运气。另外由于一些神秘的原因,glassfish的server.log被[Thread - 8] unknown.jul.logger - 时间戳...相同...输出所淹没,因此目前没有关于请求拒绝的服务器输出, 我还在Apache Tomcat 8.5.23上部署了应用程序,并在请求安全资源时出现错误消息如下:
JwtAuthenticationEntryPoint : Responding with unauthorized error. Message - Full authentication is required to access this resource
我的应用程序应该保护所有请求,除了/ api / auth / **下的那些请求,并且在IntelliJ调试模式下运行嵌入式tomcat时它完全正确。 我之前从客户端代码(使用axios)和RESTClient调用服务器如下:
(GET) http://localhost:8080/api/user/me
app.server / web容器上的:
(GET) http://localhost:8080/myproject/api/user/me
问题是,安全休息端点在IntelliJ调试模式下接受嵌入式tomcat上的经过身份验证的请求,在WAR部署之后,它神秘地拒绝所有安全请求。
我按照from spring docs使用maven进行WAR打包,GitHub page执行有关glassfish,tomcat,wildfly等的Spring启动部署测试。最后得到了一个基类如下的项目:
主类,(使用@SpringBootApplication)
@SpringBootApplication
@EntityScan(basePackageClasses = {
AccountingApplication.class,
Jsr310JpaConverters.class
})
public class AccountingApplication extends SpringBootServletInitializer{
@PostConstruct
void init() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
public static void main(String[] args) {
SpringApplication.run(applicationClass, args);
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<AccountingApplication> applicationClass = AccountingApplication.class;
}
以下是安全配置,
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
CustomUserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.
userDetailsService(userDetailsService).
passwordEncoder(passwordEncoder());
}
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
/* removed for clarity */
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/resources/**")
.permitAll()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.woff",
"/**/*.woff2",
"/**/*.ttf",
"/**/*.eot",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/auth/**")
.permitAll()
.anyRequest()
.authenticated();
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.my.project</groupId>
<artifactId>myproject-web</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>myproject-web</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<start-class>com.my.MainApplication</start-class>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</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-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</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-hateoas</artifactId>
</dependency>
<!-- Exclusion of artifacts as instructed in Spring Boot deployment docs -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Provided scope because of the dependency collision during WAR deployment -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<scope>provided</scope>
</dependency>
<!-- To access DB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- utilities -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>myproject</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
application.properties
spring.data.rest.base-path=/api
spring.datasource.url=jdbc:mysql://localhost:3306/myDB?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=1234
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.show-sql = true
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
logging.level.org.hibernate.SQL= DEBUG
# App properties
app.jwtSecret= jwtSecretKey
app.jwtExpirationInMs = 604800000
一个行为不当的控制器
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user")
public UserProfile getCurrentUser(@CurrentUser UserPrincipal currentUser) {
UserProfile userSummary = new UserProfile(currentUser.getId(), currentUser.getUsername(), currentUser.getName());
return userSummary;
}
}
最后,如果有人想知道是否有任何自定义过滤干扰了预期的流量,我会在容器启动期间显示过滤器配置。
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'errorPageFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
.s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'jwtAuthenticationFilter' to: [/*]
o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
Spring Boot ver。 2.0.1-RELEASE 构建管理。工具:Maven
很抱歉这篇长篇文章,我可以提供的任何内容只需在评论中提出。
答案 0 :(得分:1)
所以,我在问题的评论中解释了tomcat和glassfish问题,我想分享有关Wildfly部署的详细信息。
我使用Wildfly版本10.1.Final进行部署,也使用11.0.Final测试,并且不认为它会导致部署到12.0.Final的任何麻烦。
为了能够部署,您需要为主类提供上述SpringBootServletInitializer扩展,并且您需要在POM中具有以下结构。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Provided scope because of the dependency collision during WAR deployment -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
默认情况下,wildfly 10.1.Final在编写本文时使用带有Bean Validation 1.1的Hibernate Validator 5.x.Final和spring-boot-starter-web
依赖 提供了Hibernate Validator 6.0.5.Final使用Bean Validation 2.0。
因此,为了在服务器调用过程中部署而不是崩溃,由于某些验证错误,您需要生成hibernate-validator <scope>provided</scope>
并确保您拥有org.hibernate.validator ^ 6.0.5和你的应用程序中的javax.validation ^ 2.0 .jar。服务器模块。
如果有人希望分享他们关于未解决问题的智慧,那么他们非常欢迎。