Spring security loginProcessingUrl 仅适用于本地主机
Spring security loginProcessingUrl only works on localhost
我已经使用 Spring Boot 和 Thymeleaf 构建了一个应用程序。我的应用程序在本地主机中按预期工作,但是当我将其打包为 .war 并将其部署在测试 tomcat 服务器中时,它会提示登录页面,然后将我重定向到错误页面或将我带回登录页面。
我尝试了多种方法,我认为我处理 SecurityConfig.java class 中的 formLogin()
的方式存在问题。更具体地说,由于 Tomcat 在上传我的应用程序时添加了 base-url (例如从 localhost:8080
到 serverUrl:8080/reservation
),loginProcessingUrl class 可能无法识别“/process-login”class 位于 login.html 页面。
请在下面找到我的 SecurityConfig.java class
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private UserService userService;
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
private AccessDeniedHandler accessDeniedHandler;
@Autowired
public SecurityConfig(UserService userService, CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler, AccessDeniedHandler accessDeniedHandler) {
this.userService = userService;
this.customAuthenticationSuccessHandler = customAuthenticationSuccessHandler;
this.accessDeniedHandler = accessDeniedHandler;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login-form-page","/resources/**").permitAll()
.antMatchers("/", "/new-reservation", "/your-reservations","/all-reservations",
"/change-password").hasAnyRole("ADMIN","EMPLOYEE","MANAGER")
.antMatchers("/users","/user-reservations","/arrival-date","/duplicate-reservations","/all-reservations","/registration**")
.hasAnyRole("ADMIN").and()
.formLogin()
.loginPage("/login-form-page")
.loginProcessingUrl("/process-login")
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout()
.logoutUrl("/login-form-page")
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
@Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers("/resources/**", "/static/**");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
这里是 login.html 页面的一个小示例。
<div class="form-container sign-in-container">
<form id="loginForm" name="regForm" th:action="@{/process-login}"
method="POST">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<h1>Sign In</h1>
<!-- Login Error -->
<div th:if="${param.error}"
class="alert alert-danger col-xs-10">Wrong email and/or password</div>
<!-- Logout notify -->
<div th:if="${param.logout}"
class="alert alert-success 1 col-xs-10">You
have been logged out.</div>
所有 .html 页面位于
-resources
-templates
最后,我在日志中看到的唯一错误如下
DEBUG o.s.w.s.r.ResourceHttpRequestHandler - Resource not found
对于任何感兴趣的人,我设法解决了上述问题。这似乎不是 loginProcessingUrl()
class 中的配置错误。相反,问题在于远程服务器处理 JSESSIONID
和 csrf
的方式。
更具体地说,我必须做的是
- 在我的 SecurityConfig.java
中添加了以下代码块
cookieServerCsrfTokenRepository.setCookieHttpOnly(false);
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
- 接下来,添加下面的代码块
@Bean
public ServletContextInitializer servletContextInitializer(@Value("${secure.cookie}") boolean secure) {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.getSessionCookieConfig().setSecure(secure);
}
};
}
需要设置 secure.cookie
值(如果您打算使用 HTTPs 协议,application.properties
中的值为 true。
我已经使用 Spring Boot 和 Thymeleaf 构建了一个应用程序。我的应用程序在本地主机中按预期工作,但是当我将其打包为 .war 并将其部署在测试 tomcat 服务器中时,它会提示登录页面,然后将我重定向到错误页面或将我带回登录页面。
我尝试了多种方法,我认为我处理 SecurityConfig.java class 中的 formLogin()
的方式存在问题。更具体地说,由于 Tomcat 在上传我的应用程序时添加了 base-url (例如从 localhost:8080
到 serverUrl:8080/reservation
),loginProcessingUrl class 可能无法识别“/process-login”class 位于 login.html 页面。
请在下面找到我的 SecurityConfig.java class
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private UserService userService;
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
private AccessDeniedHandler accessDeniedHandler;
@Autowired
public SecurityConfig(UserService userService, CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler, AccessDeniedHandler accessDeniedHandler) {
this.userService = userService;
this.customAuthenticationSuccessHandler = customAuthenticationSuccessHandler;
this.accessDeniedHandler = accessDeniedHandler;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login-form-page","/resources/**").permitAll()
.antMatchers("/", "/new-reservation", "/your-reservations","/all-reservations",
"/change-password").hasAnyRole("ADMIN","EMPLOYEE","MANAGER")
.antMatchers("/users","/user-reservations","/arrival-date","/duplicate-reservations","/all-reservations","/registration**")
.hasAnyRole("ADMIN").and()
.formLogin()
.loginPage("/login-form-page")
.loginProcessingUrl("/process-login")
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout()
.logoutUrl("/login-form-page")
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
@Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers("/resources/**", "/static/**");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
这里是 login.html 页面的一个小示例。
<div class="form-container sign-in-container">
<form id="loginForm" name="regForm" th:action="@{/process-login}"
method="POST">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<h1>Sign In</h1>
<!-- Login Error -->
<div th:if="${param.error}"
class="alert alert-danger col-xs-10">Wrong email and/or password</div>
<!-- Logout notify -->
<div th:if="${param.logout}"
class="alert alert-success 1 col-xs-10">You
have been logged out.</div>
所有 .html 页面位于
-resources
-templates
最后,我在日志中看到的唯一错误如下
DEBUG o.s.w.s.r.ResourceHttpRequestHandler - Resource not found
对于任何感兴趣的人,我设法解决了上述问题。这似乎不是 loginProcessingUrl()
class 中的配置错误。相反,问题在于远程服务器处理 JSESSIONID
和 csrf
的方式。
更具体地说,我必须做的是
- 在我的 SecurityConfig.java 中添加了以下代码块
cookieServerCsrfTokenRepository.setCookieHttpOnly(false);
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
- 接下来,添加下面的代码块
@Bean
public ServletContextInitializer servletContextInitializer(@Value("${secure.cookie}") boolean secure) {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.getSessionCookieConfig().setSecure(secure);
}
};
}
需要设置 secure.cookie
值(如果您打算使用 HTTPs 协议,application.properties
中的值为 true。