英文:
Spring security redirects to page with status code 999
问题
以下是翻译好的部分:
成功登录后,Spring 会重定向到 /error
页面,内容如下:
{
"timestamp": 1586002411175,
"status": 999,
"error": "None",
"message": "No message available"
}
我正在使用 spring-boot 2.2.4
。
我的配置:
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.mvc.servlet.load-on-startup=1
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
@Configuration
public class DispatcherContextConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/favicon.ico", "/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.antMatchers("/registration/**").anonymous()
.anyRequest().authenticated()
.and()
.headers()
.defaultsDisabled()
.cacheControl()
.and()
.and()
.exceptionHandling()
.accessDeniedPage("/errors/403")
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/log") // 我不想在这里强制重定向
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.rememberMe()
.rememberMeParameter("remember-me")
.key("myKey");
}
// ...
}
注意:
事实证明,错误是由对我的某个静态资源的请求失败引起的。登录页面中有 <script src="/resources/my-js-file.js"></script>
,但在项目中缺失。
我可以通过移除丢失的资源导入来解决此问题,但问题可能会在将来重新出现,因此这不是一种解决方法。
如何防止这种情况发生?
我知道我可以通过 .defaultSuccessUrl("/log", true)
强制重定向到起始页,但我不想这样做。
另外,我希望重定向能在任何未找到的资源的情况下正常工作。
英文:
After successful login spring redirects to /error
page with the following content
{
"timestamp" : 1586002411175,
"status" : 999,
"error" : "None",
"message" : "No message available"
}
I'm using spring-boot 2.2.4
My config:
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.mvc.servlet.load-on-startup=1
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
@Configuration
public class DispatcherContextConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/favicon.ico", "/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/**").permitAll()
.antMatchers("/registration/**").anonymous()
.anyRequest().authenticated()
.and()
.headers()
.defaultsDisabled()
.cacheControl()
.and()
.and()
.exceptionHandling()
.accessDeniedPage("/errors/403")
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/log") // I don't want to use force redirect here
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.rememberMe()
.rememberMeParameter("remember-me")
.key("myKey");
}
// ...
}
Note:
Turns out that error is caused by failed request to one of my static resources. Login page has <script src="/resources/my-js-file.js"></script>
that is missing in the project.
I can fix this by removing missing resource import, but the problem can reappear in future so it's not a fix.
How can I prevent this from happening?
I know I can force redirect to starting page with .defaultSuccessUrl("/log", true)
but I don't want this.
Also I want redirect to work properly despite of any not found resources.
答案1
得分: 15
经过浪费了很多时间,我弄清楚了发生了什么。
所以 Spring 找不到登录页面上使用的静态资源之一。但是它不会为此资源返回状态 404
,而是尝试呈现错误页面并将请求转发到 /error
。然后 Spring Security 拒绝此请求,因为用户未经授权。它将 /error
请求保存到会话中(以便在成功登录后重定向),并将用户重定向到登录页面。
当然,用户看不到这个重定向,因为对后台完成的请求返回状态 302
。但主要问题在于会话中保存了 /error
请求。
然后用户成功登录,Spring 检查会话以获取此属性,并重定向到 /error
页面。默认情况下,[Spring 假定您在静态资源中有这样的页面][1]。如果您没有此页面,您将看到带有状态码 999 的奇怪错误。
解决方案1
在安全配置中忽略 /error
页面:
web.ignoring().antMatchers("/favicon.ico", "/resources/**", "/error");
因此,此请求将不会保存到会话中,以便在成功登录后进行用户重定向。您会发现在登录页面上,对静态资源的请求状态代码将从 302
更改为 404
。
解决方案2
在 Spring Boot 自动配置的一部分中进行忽略:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
这会产生相同的结果,但会禁用配置中的一些 bean,即 ErrorMvcAutoConfiguration
,所以请小心。
[1]: https://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling-custom-error-pages
英文:
After wasting a lot of time I figured out what's happening.
So spring can't find one of static resources that is used on login page. But instead of returning status 404
for this resource it tries to render error page and forwards request to /error
. Then spring security denies this request because user is not authorized. It saves /error
request to session (for redirecting after successful login) and redirects user to login page.
Of course user can't see this redirect because status 302
returns for request that is done in background. But the main issue is /error
request saved in session.
Then user logins successfully and spring checks session for this attribute and makes redirect to /error
page. By default [spring assumes that you have such page somewhere in static resources][1]. If you doesn't have this page you will see this weird error with status code 999.
Solution 1
Ignore /error
page in security config:
web.ignoring().antMatchers("/favicon.ico", "/resources/**", "/error");
So this request will not be saved to session for user redirection after successful login. You will see that on login page status code of request to static resource will change from 302
to 404
.
Solution 2
Ignore part of spring boot autoconfig:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
This gives same result but disables some beans from config ErrorMvcAutoConfiguration
so be careful.
[1]: https://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling-custom-error-pages
答案2
得分: 0
我也遇到了相同的问题。我尝试将每个样式表链接都注释掉,以查看哪个是导致错误的原因。结果发现是我的自定义 CSS 文件引起的。问题出在我的 CSS 文件中有一个不存在的图像 URL,还有另一个错误的 @import 语句。注释掉这些内容后,一切都正常工作了。
英文:
I had the same problem. I tried commenting every stylesheet link to see which one was causing the error. It was my custom css file. The problem was that in my css file I had an url for an image that didn't exist and also another @import statement that was wrong. After commenting these, everything worked fine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论